还有另一个关于这个的帖子,我试过了。但有一个问题:如果你删除内容,文本区域不会缩小。我找不到任何方法将其缩小到正确的大小- clientHeight值返回为文本区域的完整大小,而不是它的内容。

该页面的代码如下:

function FitToContent(id, maxHeight)
{
   var text = id && id.style ? id : document.getElementById(id);
   if ( !text )
      return;

   var adjustedHeight = text.clientHeight;
   if ( !maxHeight || maxHeight > adjustedHeight )
   {
      adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
      if ( maxHeight )
         adjustedHeight = Math.min(maxHeight, adjustedHeight);
      if ( adjustedHeight > text.clientHeight )
         text.style.height = adjustedHeight + "px";
   }
}

window.onload = function() {
    document.getElementById("ta").onkeyup = function() {
      FitToContent( this, 500 )
    };
}

当前回答

这是一种基于行的方法,允许您为文本区域设置最大行数,之后文本区域将显示滚动条。除了以rows属性的形式调整它的高度之外,它还会在键入或执行剪切和粘贴之类的操作时自动扩展它的宽度。

如果文本区域没有任何内容,只有一个占位符,它将根据占位符文本调整其宽度和高度。

这个版本的一个缺点是,它将继续无限增加它的宽度基于文本宽度。因此,你需要为文本区域设置一个max-width值。简单的max-width: 100%;也会有效果。这个宽度扩展特性主要基于type="text"的输入字段。你可以在这个答案中了解更多。

const textarea = document.querySelector('textarea'); setTextareaWidthHeight(textarea); textarea.addEventListener('input', setTextareaWidthHeight.bind(this, textarea)); function getInputWidth(element) { const text = element.value || element.placeholder; const elementStyle = window.getComputedStyle(element); const fontProperty = elementStyle.font; const horizontalBorder = parseFloat(elementStyle.borderLeftWidth) + parseFloat(elementStyle.borderRightWidth); const horizontalPadding = parseFloat(elementStyle.paddingLeft) + parseFloat(elementStyle.paddingRight); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); context.font = fontProperty; const textWidth = context.measureText(text).width; const totalWidth = horizontalBorder + horizontalPadding + textWidth + "px"; return totalWidth; } function setTextareaWidthHeight(element) { // store minimum and maximum rows attribute value that should be imposed const minRows = 1; const maxRows = 5; // store initial inline overflow property value in a variable for later reverting to original condition const initialInlineOverflowY = element.style.overflowY; // change overflow-y property value to hidden to overcome inconsistent width differences caused by any scrollbar width element.style.overflowY = 'hidden'; const totalWidth = getInputWidth(element); element.style.width = totalWidth; let rows = minRows; element.setAttribute("rows", rows); while (rows <= maxRows && element.scrollHeight !== element.clientHeight) { element.setAttribute("rows", rows); rows++; } // change overflow to its original condition if (initialInlineOverflowY) { element.style.overflowY = initialInlineOverflowY; } else { element.style.removeProperty("overflow-y"); } } textarea { max-width: 100%; } <textarea placeholder="Lorem ipsum dolor sit amet"></textarea>

其他回答

jQuery的解决方案 请根据实际情况调整CSS

css……

div#container textarea {
    min-width: 270px;
    width: 270px;
    height: 22px;
    line-height: 24px;
    min-height: 22px;
    overflow-y: hidden; /* fixes scrollbar flash - kudos to @brettjonesdev */
    padding-top: 1.1em; /* fixes text jump on Enter keypress */
}

javascript……

// auto adjust the height of
$('#container').delegate( 'textarea', 'keydown', function (){
    $(this).height( 0 );
    $(this).height( this.scrollHeight );
});
$('#container').find( 'textarea' ).keydown();

或替代jQuery 1.7+…

// auto adjust the height of
$('#container').on( 'keyup', 'textarea', function (){
    $(this).height( 0 );
    $(this).height( this.scrollHeight );
});
$('#container').find( 'textarea' ).keyup();

我已经创建了一个具有绝对最小样式的小提琴作为您的实验的起点…… http://jsfiddle.net/53eAy/951/

一个使用React的简单方法。

...
const textareaRef = useRef();

const handleChange = (e) => {
  textareaRef.current.style.height = "auto";
  textareaRef.current.style.height = textareaRef.current.scrollHeight + "px";
};

return <textarea ref={textareaRef} onChange={handleChange} />;

我的实现非常简单,计算输入中的行数(并且最少2行,以显示它是一个textarea):

textarea.rows = Math.max(2, textarea.value.split("\n").length) // # oninput

刺激的完整工作示例:https://jsbin.com/kajosolini/1/edit?html,js,output

(这适用于浏览器的手动调整大小句柄,例如)

对于那些正在寻找特定角度的答案的人,你可以使用这个选项来设置默认行数。

create directive

    @Directive({
  selector: '[appTextAreaAutoHeight]'
})
export class TextAreaAutoHeightDirective implements AfterViewInit {
  private row = 1;
  constructor(private el: ElementRef) {
    this.row = el.nativeElement.rows;
  }
  ngAfterViewInit(): void {
    const elem = this.el.nativeElement;
    elem.style.height = "1px";
    elem.style.minHeight = (this.row * elem.scrollHeight) + "px";
  }

  @HostListener('input', ['$event.target'])
  onInput(elem: any) {
    elem.style.height = "1px";
    elem.style.height = (elem.scrollHeight) + "px";
  }
}

使用方法:

<textarea id="title" rows="3" class="col-12 p-1 fs-15 fw-reg 
  rounded-1" appTextAreaAutoHeight
  placeholder="...*******$$$"></textarea>

下面的工作用于剪切,粘贴等,不管这些操作是来自鼠标,键盘快捷键,从菜单栏选择一个选项…有几个答案采用了类似的方法,但它们没有考虑到box-sizing,这就是为什么它们错误地应用了样式overflow: hidden。

我执行以下操作,这也适用于max-height和rows的最小高度和最大高度。

function adjust() { var style = this.currentStyle || window.getComputedStyle(this); var boxSizing = style.boxSizing === 'border-box' ? parseInt(style.borderBottomWidth, 10) + parseInt(style.borderTopWidth, 10) : 0; this.style.height = ''; this.style.height = (this.scrollHeight + boxSizing) + 'px'; }; var textarea = document.getElementById("ta"); if ('onpropertychange' in textarea) { // IE textarea.onpropertychange = adjust; } else if ('oninput' in textarea) { textarea.oninput = adjust; } setTimeout(adjust.bind(textarea)); textarea { resize: none; max-height: 150px; border: 1px solid #999; outline: none; font: 18px sans-serif; color: #333; width: 100%; padding: 8px 14px; box-sizing: border-box; } <textarea rows="3" id="ta"> Try adding several lines to this. </textarea>

为了绝对完整,你应该在以下几种情况下调用adjust函数:

窗口调整大小事件(如果文本区域的宽度随着窗口调整大小而改变),或者其他改变文本区域宽度的事件 当文本区域的显示样式属性发生变化时,例如当它从none(隐藏)变为block时 当文本区域的值以编程方式更改时

注意使用window。getComputedStyle或getcurrentstyle在计算上可能有点昂贵,所以您可能想要缓存结果。

适用于IE6,所以我真的希望这是足够好的支持。