还有另一个关于这个的帖子,我试过了。但有一个问题:如果你删除内容,文本区域不会缩小。我找不到任何方法将其缩小到正确的大小- 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 )
    };
}

当前回答

本地Javascript解决方案没有闪烁在Firefox和更快的方法与clientheight…

1)将div.textarea selector添加到所有包含textarea的选择器中。不要忘记添加box-sizing: border-box;

2)包括以下脚本:

function resizeAll()
{
   var textarea=document.querySelectorAll('textarea');
   for(var i=textarea.length-1; i>=0; i--)
      resize(textarea[i]);
}

function resize(textarea)
{
   var div = document.createElement("div");
   div.setAttribute("class","textarea");
   div.innerText=textarea.value+"\r\n";
   div.setAttribute("style","width:"+textarea.offsetWidth+'px;display:block;height:auto;left:0px;top:0px;position:fixed;z-index:-200;visibility:hidden;word-wrap:break-word;overflow:hidden;');
   textarea.form.appendChild(div);
   var h=div.offsetHeight;
   div.parentNode.removeChild(div);
   textarea.style.height=h+'px';
}

function resizeOnInput(e)
{
   var textarea=document.querySelectorAll('textarea');
   for(var i=textarea.length-1; i>=0; i--)
      textarea[i].addEventListener("input",function(e){resize(e.target); return false;},false);
}

window.addEventListener("resize",function(){resizeAll();}, false);
window.addEventListener("load",function(){resizeAll();}, false);
resizeOnInput();

在IE11、Firefox和Chrome上测试。

这个解决方案创建div类似于您的文本区域,包括内部文本和测量高度。

其他回答

这是一个angularjs指令,用于panzi的答案。

 module.directive('autoHeight', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element = element[0];
                var resize = function(){
                    element.style.height = 'auto';
                    element.style.height = (element.scrollHeight)+'px';
                };
                element.addEventListener('change', resize, false);
                element.addEventListener('cut',    resize, false);
                element.addEventListener('paste',  resize, false);
                element.addEventListener('drop',   resize, false);
                element.addEventListener('keydown',resize, false);

                setTimeout(resize, 100);
            }
        };
    });

HTML:

<textarea ng-model="foo" auto-height></textarea>

我在常见的浏览器中测试了脚本,在Chrome和Safari中失败了。这是因为不断更新的scrollHeight变量。

我已经使用jQuery应用了wrettledgoat脚本,并添加了chrome修复

function fitToContent(/* JQuery */text, /* Number */maxHeight) {
    var adjustedHeight = text.height();
    var relative_error = parseInt(text.attr('relative_error'));
    if (!maxHeight || maxHeight > adjustedHeight) {
        adjustedHeight = Math.max(text[0].scrollHeight, adjustedHeight);
        if (maxHeight)
            adjustedHeight = Math.min(maxHeight, adjustedHeight);
        if ((adjustedHeight - relative_error) > text.height()) {
            text.css('height', (adjustedHeight - relative_error) + "px");
            // chrome fix
            if (text[0].scrollHeight != adjustedHeight) {
                var relative = text[0].scrollHeight - adjustedHeight;
                if (relative_error != relative) {
                    text.attr('relative_error', relative + relative_error);
                }
            }
        }
    }
}

function autoResizeText(/* Number */maxHeight) {
    var resize = function() {
        fitToContent($(this), maxHeight);
    };
    $("textarea").attr('relative_error', 0);
    $("textarea").each(resize);
    $("textarea").keyup(resize).keydown(resize);
}

稍微更正一下。完美演绎歌剧

  $('textarea').bind('keyup keypress', function() {
      $(this).height('');
      var brCount = this.value.split('\n').length;
      this.rows = brCount+1; //++ To remove twitching
      var areaH = this.scrollHeight,
          lineHeight = $(this).css('line-height').replace('px',''),
          calcRows = Math.floor(areaH/lineHeight);
      this.rows = calcRows;
  });

我创建了一个小的(7kb)自定义元素,为您处理所有这些调整大小的逻辑。

它可以在任何地方工作,因为它是作为自定义元素实现的。包括:虚拟dom (React, Elm等),服务器端呈现的东西,如PHP和简单乏味的HTML文件。

除了监听输入事件外,它还有一个计时器,每100毫秒触发一次,以确保在文本内容通过其他方式发生变化的情况下,事情仍在工作。

下面是它的工作原理:

// At the top of one of your Javascript files
import "autoheight-textarea";

或作为脚本标记包含

<script src="//cdn.jsdelivr.net/npm/autoheight-textarea@1.0.1/dist/main.min.js"></script>

然后像这样包装你的textarea元素

HTML文件

<autoheight-textarea>
  <textarea rows="4" placeholder="Type something"></textarea>
<autoheight-textarea>

React.js组件

const MyComponent = () => {
  return (
    <autoheight-textarea>
      <textarea rows={4} placeholder="Type something..." />
    </autoheight-textarea>
  );
}

下面是Codesandbox上的一个基本演示:https://codesandbox.io/s/unruffled-http-2vm4c

你可以在这里获取软件包:https://www.npmjs.com/package/autoheight-textarea

如果你只是想看看调整大小的逻辑,你可以看看这个函数:https://github.com/Ahrengot/autoheight-textarea/blob/master/src/index.ts#L74-L85

作为一种不同的方法,您可以使用<span>来自动调整它的大小。你需要通过添加contentteditable ="true"属性使其可编辑,这样就完成了:

div { 宽度:200 px; } 跨度{ 边框:1px实心#000; 填充:5 px; } < div > <span contenteditable="true">此文本可以由用户编辑</span> < / div >

这种方法的唯一问题是,如果希望将值作为表单的一部分提交,就必须自己用JavaScript完成。这样做相对容易。例如,您可以添加一个隐藏字段,并在表单的onsubmit事件中将span的值赋给隐藏字段,然后该隐藏字段将自动与表单一起提交。