24

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

4

3 回答 3

17

2020 更新 - 使用contenteditable

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

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

在 a 上使用contenteditableHTML 属性<div />将允许用户编辑 a 的文本内容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;
}

这个解决方案的一个警告是,我们没有使用 textareas。请记住,某些功能(例如占位符)将需要一些创造力才能使用<div contenteditable />

资料来源:伟大的 Chris Coiyer。链接到他的博客


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

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

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

这是包含演示和使用的链接。

npm install autosize您可以通过这样做和使用这种方式来安装它

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

或者 jQuery 风格

autosize($('.yourTextAreaClass'));

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

于 2016-05-02T13:17:05.990 回答
12

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 )

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

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

本软件按“原样”提供,不提供任何形式的明示或暗示保证,包括但不限于适销性、特定用途适用性和非侵权保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任承担任何责任,无论是在合同诉讼、侵权行为或其他方面,由本软件或本软件的使用或其他交易引起或与之相关。软件。

于 2020-11-11T19:31:56.543 回答
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 解决方案应该很容易推断,只需要在输入/更改的元素上应用事件侦听器即可。

于 2017-06-13T05:55:13.763 回答