在一个起初是小框且单行的文本区域中,是否可以使用CSS使其随着用户输入多行而自动增加行数,直到达到设定的限制(300px),然后出现带有overflow属性为auto的滚动条以满足所有输入?
2020年更新 - 使用contenteditable
由于这个答案仍然有时对一些人有所帮助,我觉得应该更新一下我的答案,加入Chris Coyier最新的发现。
需要注意的是,这仍然不是CSS3的解决方案。但它是内置在浏览器中的,并且可以重新创建OP所寻求的行为。
在<div />
上使用contenteditable
HTML属性将允许用户编辑div
的文本内容,并随着用户换行而扩展。然后,只需将您的div
伪装成<textarea />
即可。
<div
class="expandable-textarea"
role="textbox"
contenteditable
>
Your default value
</div>
.expandable-textarea {
border: 1px solid #ccc;
font-family: inherit;
font-size: inherit;
padding: 1px 6px;
display: block;
width: 100%;
overflow: hidden;
resize: both;
min-height: 40px;
line-height: 20px;
}
这种解决方案有一个限制,即我们不使用文本区域(textarea)。请记住,一些功能(例如 placeholder)需要使用<div contenteditable />
实现一些创意。
来源:Chris Coiyer大神的博客。链接
使用轻量级JS库的解决方法
不幸的是,似乎无法仅使用CSS3实现此功能。
但是,有一种体积为3.2k的JS替代方案可以做到。
这里是链接,包括演示和用法。
您可以通过执行 npm install autosize
来安装它,并使用以下方式:
autosize(document.querySelector('.yourTextAreaClass'));
或者使用 jQuery 风格
autosize($('.yourTextAreaClass'));
它的效果非常好。它很轻巧,使用起来自然感觉良好,不像许多做无用动画的自动调整大小插件。
CodePen网站的创始人Chris Coyier最近发布了一个基于网格的纯CSS实现。原始代码来自Chris Coyier在2020年10月30日发布的CodePen
.grow-wrap { /* easy way to plop the elements on top of each other and have them both sized based on the tallest one's height */ display: grid; } .grow-wrap::after { /* Note the weird space! Needed to preventy jumpy behavior */ content: attr(data-replicated-value) " "; /* This is how textarea text behaves */ white-space: pre-wrap; /* Hidden from view, clicks, and screen readers */ visibility: hidden; } .grow-wrap>textarea { /* You could leave this, but after a user resizes, then it ruins the auto sizing */ resize: none; /* Firefox shows scrollbar on growth, you can hide like this. */ overflow: hidden; } .grow-wrap>textarea, .grow-wrap::after { /* Identical styling required!! */ border: 1px solid black; padding: 0.5rem; font: inherit; /* Place on top of each other */ grid-area: 1 / 1 / 2 / 2; } body { margin: 2rem; font: 1rem/1.4 system-ui, sans-serif; } label { display: block; }
<form action="#0"> <label for="text">Text:</label> <div class="grow-wrap"> <textarea name="text" id="text" onInput="this.parentNode.dataset.replicatedValue = this.value"></textarea> </div> </form>
许可证:
版权所有(c)2020年 Chris Coyier (https://codepen.io/chriscoyier/pen/XWKEVLy)
特此免费授予任何获得本软件及相关文档文件(以下简称“软件”)副本的人,无限制地处理该软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售该软件的副本,并允许被授权人员这样做,但必须遵守以下条件:
所有副本或重要部分的软件必须包含上述版权声明和本许可声明。
软件是按“原样”提供的,没有任何形式的明示或暗示保证,包括但不限于适销性、特定用途的适用性和非侵权性。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任承担任何责任,无论是合同诉讼、侵权行为还是其他行为,由于软件或其使用或其他途径而引起。
angular.module('Shared.AutoGrow.Directive', [])
.directive('autoGrow', function() {
return {
restrict: 'A',
link(scope, element) {
element.on('input change', () => {
const text = element[0].value;
const lines = 1 + (text.match(/\n/g) || []).length;
element[0].rows = lines;
});
},
};
});
普通的JS解决方案应该很容易推断,只需要在输入/更改元素上应用事件监听器就可以了。