如何使用CSS自动增长文本区域?

问题描述 投票:0回答:4

给定一个以小框、单行开始的文本区域,当用户键入多行时,是否可以使用CSS自动增长为多行,直到达到设定限制(300px),此时滚动条会出现溢出自动与所有的输入?

html css
4个回答
18
投票

2020 更新 - 使用

contenteditable

因为这个答案仍然时不时地对一些人有帮助,所以我想用 Chris Coiyer 的最新发现更新我的答案。

请注意,它仍然不是 CSS3 解决方案。但它内置于浏览器中,并重新创建了 OP 所寻求的行为。

contenteditable
上使用
<div />
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;
}

此解决方案的一个警告是我们没有使用文本区域。请记住,某些功能(例如占位符)需要一些创造力才能使用

<div contenteditable />

来实现

来源:伟大的克里斯·科耶尔。 链接到他的博客


原始答案:使用轻量级 JS 库的解决方法

不幸的是,似乎仅使用 CSS3 无法做到这一点。

但是,有一个 3.2k 的缩小版 JS 替代方案可以做到这一点。

这是链接,包括演示和用法。

您可以通过执行

npm install autosize
并使用这种方式来安装它

autosize(document.querySelector('.yourTextAreaClass'));

或者 jQuery 风格

autosize($('.yourTextAreaClass'));

它就像一个魅力。它很轻量级并且具有自然的感觉,不像许多自动调整大小那样做无用的动画。


17
投票

Chris Coyier(CodePen 出名)刚刚发布了一个基于网格的 CSS 实现。来自 Chris Coyier 的原始 CodePen - 2020 年 10 月 30 日

.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)

特此免费授予获得本软件和相关文档文件(“软件”)副本的任何人不受限制地使用本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件的副本,并允许向其提供软件的人员这样做,但须满足以下条件:

上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。

本软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有者均不对因本软件或本软件中的使用或其他交易而产生或与之相关的任何索赔、损害或其他责任负责,无论是合同、侵权行为还是其他行为。软件。


1
投票

据我所知,仅使用 CSS 是不可能的,但这里有一个超级小的 Angular 指令,只需检查新行即可工作。您可以轻松调整它以具有最大行数等。

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 解决方案应该很容易推断,只需要在输入/更改时在元素上应用事件侦听器即可。


0
投票

使用 Alpinjs,这是一个简单的解决方案

<textarea 
    x-data="{
        init() {
            this.resize();
        },
        resize() {
            $el.style.height = '80px';
            $el.style.height = Math.min(300, $el.scrollHeight + 10) + 'px';
        },
    }"
    x-on:input="resize()"
></textarea>
© www.soinside.com 2019 - 2024. All rights reserved.