【问题标题】:Creating a textarea with auto-resize创建具有自动调整大小的文本区域
【发布时间】:2010-10-02 00:53:58
【问题描述】:

another thread about this,我试过了。但是有一个问题:如果您删除内容,textarea 不会缩小。我找不到任何方法将其缩小到正确的大小 - clientHeight 值返回为 textarea 的完整大小,而不是其内容。

该页面的代码如下:

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 html resize height textarea


【解决方案1】:

完整而简单的解决方案

更新2020-05-14 (改进了对手机和平板电脑的浏览器支持)

以下代码将起作用:

  • 关于按键输入。
  • 粘贴文本(右键单击 & ctrl+v)。
  • 带有剪切文本(右键单击 & ctrl+x)。
  • 带有预加载的文本。
  • 所有文本区域的(多行文本框) 站点范围内。
  • 使用 Firefox (已测试 v31-67)。
  • 使用 Chrome (已通过 v37-74 测试)。
  • 使用 IE (已通过 v9-v11 测试)。
  • 使用 Edge (已通过 v14-v18 测试)。
  • 使用 IOS Safari
  • 使用 Android 浏览器
  • 使用 JavaScript 严格模式
  • 是否经过 w3c 验证。
  • 精简高效。

选项 1 (使用 jQuery)

此选项需要jQuery,并且已经过测试并且可以与1.7.2 - 3.6

一起使用

简单 (将此 jquery 代码添加到您的主脚本文件中,然后忘记它。)

$("textarea").each(function () {
  this.setAttribute("style", "height:" + (this.scrollHeight) + "px;overflow-y:hidden;");
}).on("input", function () {
  this.style.height = "auto";
  this.style.height = (this.scrollHeight) + "px";
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT.
This javascript should now add better support for IOS browsers and Android browsers.</textarea>
<textarea placeholder="Type, paste, cut text here..."></textarea>

Test on jsfiddle


选项 2 (纯 JavaScript)

简单 (将此 JavaScript 添加到您的主脚本文件中,然后忘记它。)

const tx = document.getElementsByTagName("textarea");
for (let i = 0; i < tx.length; i++) {
  tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;");
  tx[i].addEventListener("input", OnInput, false);
}

function OnInput() {
  this.style.height = "auto";
  this.style.height = (this.scrollHeight) + "px";
}
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This JavaScript should now add better support for IOS browsers and Android browsers.</textarea>
<textarea placeholder="Type, paste, cut text here..."></textarea>

Test on jsfiddle


选项 3 (jQuery 扩展)

如果您想将进一步的链接应用到您想要自动调整大小的文本区域,这很有用。

jQuery.fn.extend({
  autoHeight: function () {
    function autoHeight_(element) {
      return jQuery(element)
        .css({ "height": "auto", "overflow-y": "hidden" })
        .height(element.scrollHeight);
    }
    return this.each(function() {
      autoHeight_(this).on("input", function() {
        autoHeight_(this);
      });
    });
  }
});

使用$("textarea").autoHeight() 调用


通过 JAVASCRIPT 更新文本区域

当通过 JavaScript 将内容注入文本区域时,附加以下代码以调用选项 1 中的函数。

$("textarea").trigger("input");

预设文本区域高度

要修复 textarea 的初始高度,您需要添加一个附加条件:

const txHeight = 16;
const tx = document.getElementsByTagName("textarea");

for (let i = 0; i < tx.length; i++) {
  if (tx[i].value == '') {
    tx[i].setAttribute("style", "height:" + txHeight + "px;overflow-y:hidden;");
  } else {
    tx[i].setAttribute("style", "height:" + (tx[i].scrollHeight) + "px;overflow-y:hidden;");
  }
  tx[i].addEventListener("input", OnInput, false);
}

function OnInput(e) {
  this.style.height = "auto";
  this.style.height = (this.scrollHeight) + "px";
}
<textarea placeholder="Type, paste, cut text here...">PRELOADED TEXT. This JavaScript should now add better support for IOS browsers and Android browsers.</textarea>
<textarea placeholder="Type, paste, cut text here..."></textarea>

【讨论】:

  • 这是一个很好的解决方案,如果将方法名称和参数名称更新为真实名称而不是单个字母会更容易理解。
  • @Obsidian 谢谢!我刚刚弄清楚为什么我总是得到一个 0 —— 我把 textarea 放在了 Bootstrap modal 中!由于模态框最初是隐藏的,因此其中的 textarea 将有一个 0 scrollHeight ??
  • @黑曜石太棒了!! (选项 3)。 this.style.height = 'auto'; 是神奇的行为修复。我很沮丧为什么 scrollHeight 的行为如此奇怪。自动的高度,然后在同一个渲染周期中匹配 scrollHeight 仍然让我大吃一惊,尽管它在技术上应该只是绘制第二个高度。
  • 我今天在 Chrome 中尝试了选项 3,并且不得不进行一些调整。 1)如果您在文本区域上有“高度”或“全部”过渡,它不会总是正确调整大小。我建议不要使用影响高度的过渡。 2) scrollHeight 返回最少两行的高度(可能是因为这是 Chrome 中 textareas 的默认设置)但是如果您更改 this.style.height = 'auto';到 this.style.height = '0px';并添加一个 min-height 以防止初始状态实际变为 0,scrollHeight 将在适当时正确返回一行高度。
  • @Obsidian 你能解释一下this.style.height = 'auto'; 是如何修复scrollHeight 的吗?这只是魔术。
【解决方案2】:

使用 React 的示例实现:

const {
  useLayoutEffect,
  useState,
  useRef
} = React;

const TextArea = () => {
  const ref = useRef();
  const [value, setValue] = useState('Some initial text that both wraps and uses\nnew\nlines');

  // This only tracks the auto-sized height so we can tell if the user has manually resized
  const autoHeight = useRef();

  useLayoutEffect(() => {
    if (!ref.current) {
      return;
    }

    if (
      autoHeight.current !== undefined &&
      ref.current.style.height !== autoHeight.current
    ) {
      // don't auto size if the user has manually changed the height
      return;
    }

    ref.current.style.height = "auto";
    ref.current.style.overflow = "hidden";
    const next = `${ref.current.scrollHeight}px`;
    ref.current.style.height = next;
    autoHeight.current = next;
    ref.current.style.overflow = "auto";
  }, [value, ref, autoHeight]);


  return (
    <textarea
      ref={ref}
      style={{
        resize: 'vertical',
        minHeight: '1em',
      }}
      value={value}
      onChange={event => setValue(event.target.value)}
    />
  );
}

ReactDOM.render(<TextArea />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

【讨论】:

    【解决方案3】:

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

    如果textarea除了占位符之外没有任何内容,它将根据占位符文本调整其宽度和高度。

    此版本的一个缺点是它会继续根据文本宽度无限增加其宽度。因此,您需要将max-width 值设置为textarea。一个简单的max-width: 100%; 也可以解决问题。此宽度扩展功能主要基于type="text"input 字段。您可以在answer 中了解更多信息。

    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%;
    }
    &lt;textarea placeholder="Lorem ipsum dolor sit amet"&gt;&lt;/textarea&gt;

    【讨论】:

      【解决方案4】:

      对于 Angular 2+,只需这样做

      <textarea (keydown)="resize($event)"></textarea>
      
      
      resize(e) {
          setTimeout(() => {
            e.target.style.height = 'auto';
            e.target.style.height = (e.target.scrollHeight)+'px';
          }, 0);
        }
      
      textarea {
        resize: none;
        overflow: hidden;
      }
      

      【讨论】:

        【解决方案5】:

        我知道我迟到了,但我遇到的最简单的解决方案是将文本区域内容拆分为换行符并更新 textarea 元素的行。

        <textarea id="my-text-area"></textarea>
        
        <script>
          $(function() {
            const txtArea = $('#my-text-area')
            const val = txtArea.val()
            const rowLength = val.split('\n')
            txtArea.attr('rows', rowLength)
          })
        </script>
        

        【讨论】:

          【解决方案6】:

          我将以下代码用于多个文本区域。在 Chrome 12、Firefox 5 和 IE 9 中运行良好,即使在 textareas 中执行删除、剪切和粘贴操作也是如此。

          function attachAutoResizeEvents() {
            for (i = 1; i <= 4; i++) {
              var txtX = document.getElementById('txt' + i)
              var minH = txtX.style.height.substr(0, txtX.style.height.indexOf('px'))
              txtX.onchange = new Function("resize(this," + minH + ")")
              txtX.onkeyup = new Function("resize(this," + minH + ")")
              txtX.onchange(txtX, minH)
            }
          }
          
          function resize(txtX, minH) {
            txtX.style.height = 'auto' // required when delete, cut or paste is performed
            txtX.style.height = txtX.scrollHeight + 'px'
            if (txtX.scrollHeight <= minH)
              txtX.style.height = minH + 'px'
          }
          window.onload = attachAutoResizeEvents
          textarea {
            border: 0 none;
            overflow: hidden;
            outline: none;
            background-color: #eee
          }
          <textarea style='height:100px;font-family:arial' id="txt1"></textarea>
          <textarea style='height:125px;font-family:arial' id="txt2"></textarea>
          <textarea style='height:150px;font-family:arial' id="txt3"></textarea>
          <textarea style='height:175px;font-family:arial' id="txt4"></textarea>

          【讨论】:

            【解决方案7】:

            有没有人认为 contenteditable?不要乱用滚动,我唯一喜欢它的 JS 是如果你打算将数据保存在模糊中......显然,它在所有流行的浏览器上都兼容:http://caniuse.com/#feat=contenteditable

            只需将其设置为看起来像一个文本框,它会自动调整大小...将其最小高度设置为首选文本高度并使用它。

            这种方法的好处在于您可以在某些浏览器上保存和标记。

            http://jsfiddle.net/gbutiri/v31o8xfo/

            var _auto_value = '';
            $(document).on('blur', '.autosave', function(e) {
              var $this = $(this);
              if ($this.text().trim() == '') {
                $this.html('');
              }
            
              // The text is here. Do whatever you want with it.
              $this.addClass('saving');
            
              if (_auto_value !== $this.html() || $this.hasClass('error')) {
            
                // below code is for example only.
                $.ajax({
                  url: '/echo/json/?action=xyz_abc',
                  data: 'data=' + $this.html(),
                  type: 'post',
                  datatype: 'json',
                  success: function(d) {
                    console.log(d);
                    $this.removeClass('saving error').addClass('saved');
                    var k = setTimeout(function() {
                      $this.removeClass('saved error')
                    }, 500);
                  },
                  error: function() {
                    $this.removeClass('saving').addClass('error');
                  }
                });
              } else {
                $this.removeClass('saving');
              }
            }).on('focus mouseup', '.autosave', function() {
              var $this = $(this);
              if ($this.text().trim() == '') {
                $this.html('');
              }
              _auto_value = $this.html();
            }).on('keyup', '.autosave', function(e) {
              var $this = $(this);
              if ($this.text().trim() == '') {
                $this.html('');
              }
            });
            body {
              background: #3A3E3F;
              font-family: Arial;
            }
            
            label {
              font-size: 11px;
              color: #ddd;
            }
            
            .autoheight {
              min-height: 16px;
              font-size: 16px;
              margin: 0;
              padding: 10px;
              font-family: Arial;
              line-height: 20px;
              box-sizing: border-box;
              -o-box-sizing: border-box;
              -moz-box-sizing: border-box;
              -webkit-box-sizing: border-box;
              overflow: hidden;
              display: block;
              resize: none;
              border: 0;
              outline: none;
              min-width: 200px;
              background: #ddd;
              max-height: 400px;
              overflow: auto;
            }
            
            .autoheight:hover {
              background: #eee;
            }
            
            .autoheight:focus {
              background: #fff;
            }
            
            .autosave {
              -webkit-transition: all .2s;
              -moz-transition: all .2s;
              transition: all .2s;
              position: relative;
              float: none;
            }
            
            .autoheight * {
              margin: 0;
              padding: 0;
            }
            
            .autosave.saving {
              background: #ff9;
            }
            
            .autosave.saved {
              background: #9f9;
            }
            
            .autosave.error {
              background: #f99;
            }
            
            .autosave:hover {
              background: #eee;
            }
            
            .autosave:focus {
              background: #fff;
            }
            
            [contenteditable=true]:empty:before {
              content: attr(placeholder);
              color: #999;
              position: relative;
              top: 0px;
              /*
                For IE only, do this:
                position: absolute;
                top: 10px;
                */
              cursor: text;
            }
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
            <label>Your Name</label>
            <div class="autoheight autosave contenteditable" contenteditable="true" placeholder="Your Name"></div>

            【讨论】:

            • Chrome 会在 ENTER 上添加
              元素。
            • contenteditable 很好,但如果你想要纯文本,它需要一堆选项,如 -webkit-user-modify: read-write-plaintext-onlywhite-space: pre-wrap
            • @_sbaechler:使用[dom-element].innerText时省略
              。 @WebmasterG 恕我直言,省略 jquery(为了透明)并通过可运行的代码片段而不是 jsfiddle 在此页面上包含示例会很好。
            【解决方案8】:

            这是 Moussawi7answer 的 jQuery 版本。

            $(function() {
              $("textarea.auto-grow").on("input", function() {
                var element = $(this)[0];
                element.style.height = "5px";
                element.style.height = (element.scrollHeight) + "px";
              });
            })
            textarea {
              resize: none;
              overflow: auto;
              width: 100%;
              min-height: 50px;
              max-height: 150px;
            }
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
            <textarea class="auto-grow"></textarea>

            【讨论】:

              【解决方案9】:

              here找到一个班轮;

              <textarea name="text" oninput="this.style.height = ''; this.style.height = this.scrollHeight +'px'"></textarea>
              

              【讨论】:

                【解决方案10】:

                接受的答案工作正常。但对于这个简单的功能来说,这是很多代码。下面的代码可以解决问题。

                   $(document).on("keypress", "textarea", function (e) {
                    var height = $(this).css("height");
                    var iScrollHeight = $(this).prop("scrollHeight");
                    $(this).css('height',iScrollHeight);
                    });
                

                【讨论】:

                  【解决方案11】:

                  我创建了 a small (7kb) custom element 来为您处理所有这些调整大小的逻辑。

                  它适用于任何地方,因为它是作为自定义元素实现的。包括:虚拟 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

                  【讨论】:

                    【解决方案12】:

                    我的实现很简单,计算输入中的行数(最少2行表明它是一个textarea):

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

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

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

                    【讨论】:

                    • 这只有在你按“enter”换行时才有效。如果您的文本比文本区域的宽度长,但您没有按“回车”,它不会展开。
                    【解决方案13】:

                    那些希望在新版本的 Angular 中实现相同目标的人。

                    抓取 textArea elementRef.

                    @ViewChild('textArea', { read: ElementRef }) textArea: ElementRef;
                    
                    public autoShrinkGrow() {
                        textArea.style.overflow = 'hidden';
                        textArea.style.height = '0px';
                        textArea.style.height = textArea.scrollHeight + 'px';
                    }
                    
                    <textarea (keyup)="autoGrow()" #textArea></textarea>
                    

                    我还添加了另一个用例,可能会派上用场一些用户阅读线程,当用户想要将文本区域的高度增加到一定高度然后上面有overflow:scroll时,可以扩展上述方法来实现提到的用例。

                      public autoGrowShrinkToCertainHeight() {
                        const textArea = this.textArea.nativeElement;
                        if (textArea.scrollHeight > 77) {
                          textArea.style.overflow = 'auto';
                          return;
                        }
                        else {
                          textArea.style.overflow = 'hidden';
                          textArea.style.height = '0px';
                          textArea.style.height = textArea.scrollHeight + 'px';
                        }
                      }
                    

                    【讨论】:

                      【解决方案14】:

                      我发现的最佳方式:

                      $("textarea.auto-grow").each( function(){
                          $(this).keyup(function(){
                              $(this).height( $(this)[0].scrollHeight - Number( $(this).css("font-size").replace("px", "") ) );
                          });
                      });
                      

                      其他方式有字体大小错误。

                      这就是为什么这是最好的。

                      【讨论】:

                        【解决方案15】:

                        您可以在键入时使用 JQuery 扩展 textarea

                        $(document).find('textarea').each(function () {
                          var offset = this.offsetHeight - this.clientHeight;
                        
                          $(this).on('keyup input focus', function () {
                            $(this).css('height', 'auto').css('height', this.scrollHeight + offset);
                          });
                        });
                        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
                        
                        <div>
                        <textarea name="note"></textarea>
                        <div>

                        【讨论】:

                        • 最干净的解决方案。但是我们应该停止使用 jQuery: textarea.addEventListener('keyup', () => { textarea.style.height = 0; textarea.style.height = ${textarea.scrollHeight}px; });
                        【解决方案16】:

                        自动调整大小

                        https://github.com/jackmoore/autosize

                        Just works,独立,很受欢迎(截至 2018 年 10 月,GitHub 星数超过 3.0k),在 cdnjs 上可用)和轻量级(~3.5k)。演示:

                        <textarea id="autosize" style="width:200px;">a
                        J   b
                        c</textarea>
                        <script src="https://cdnjs.cloudflare.com/ajax/libs/autosize.js/4.0.2/autosize.min.js"></script>
                        <script>autosize(document.querySelectorAll('#autosize'));</script>

                        顺便说一句,如果您使用的是 ACE 编辑器,请使用 maxLines: InfinityAutomatically adjust height to contents in Ace Cloud 9 editor

                        【讨论】:

                        • 2015年2月发布第二版,变得更简单,不再依赖jQuery
                        • 对不起,它确实有效。也许我在其他浏览器中..所以,我认为您最好忽略我的评论..
                        • @ToniMichelCaubet 啊,好吧,那可能是 CDN 问题。让我检查一下。
                        • autosize 插件不允许使用 textarea 中的调整大小图标手动调整大小。
                        • @j4v1, css: #autosize{resize:vertical !important}
                        【解决方案17】:

                        似乎没有一个答案有效。但这对我有用: https://coderwall.com/p/imkqoq/resize-textarea-to-fit-content

                        $('#content').on( 'change keyup keydown paste cut', 'textarea', function (){
                            $(this).height(0).height(this.scrollHeight);
                        }).find( 'textarea' ).change();
                        

                        【讨论】:

                        • 这应该是公认的答案,尽管听“keyup”事件就足够了
                        【解决方案18】:

                        使用 qQuery 的 MakeTextAreaResisable

                        function MakeTextAreaResisable(id) {
                            var o = $(id);
                            o.css("overflow-y", "hidden");
                        
                            function ResizeTextArea() {
                                o.height('auto');
                                o.height(o[0].scrollHeight);
                            }
                        
                            o.on('change', function (e) {
                                ResizeTextArea();
                            });
                        
                            o.on('cut paste drop keydown', function (e) {
                                window.setTimeout(ResizeTextArea, 0);
                            });
                        
                            o.focus();
                            o.select();
                            ResizeTextArea();
                        }
                        

                        【讨论】:

                          【解决方案19】:

                          作为一种不同的方法,您可以使用&lt;span&gt;,它会自动调整其大小。您需要通过添加 contenteditable="true" 属性使其可编辑,然后您就完成了:

                          div {
                            width: 200px;
                          }
                          
                          span {
                            border: 1px solid #000;
                            padding: 5px;
                          }
                          <div>
                            <span contenteditable="true">This text can be edited by the user</span>
                          </div>

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

                          【讨论】:

                          • 本页已有使用 contenteditable 的答案:stackoverflow.com/questions/454202/…
                          • @adabru 是的,但是两个答案不一样。丰田生产红色汽车,福特也生产红色汽车,但它们不同,不是吗?如果您更喜欢另一个答案,那就去吧。但是有些人更欣赏我的回答并接受它。有不同的选择很好。
                          【解决方案20】:

                          这是 panzi 回答的 angularjs 指令。

                           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>
                          

                          【讨论】:

                          • 你应该使用 $timeout 而不是 setTimout - 这将确保模型被初始化(无需指定毫秒 - 它会在 Angular 摘要循环之后执行)。还有 element = element[0];是一个非常糟糕的做法......无论如何,解决方案对我没有好处,因为我需要 textarea 是单行的,直到有更多的文本。
                          【解决方案21】:

                          在 Firefox 中没有闪烁的原生 Javascript 解决方案,并且比 withclientHeight 的方法更快...

                          1) 将div.textarea 选择器添加到所有包含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,包括内部文本和测量高度。

                          【讨论】:

                            【解决方案22】:

                            以下适用于剪切、粘贴等操作,无论这些操作是否来自鼠标、键盘快捷键、从菜单栏中选择一个选项......有几个答案采用类似的方法,但他们不考虑对于 box-sizing,这就是他们错误地应用样式 overflow: hidden 的原因。

                            我执行以下操作,这对于最小和最大高度也适用于 max-heightrows

                            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 函数:

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

                            请注意,使用window.getComputedStyle 或获取currentStyle 在计算上可能会有些昂贵,因此您可能希望改为缓存结果。

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

                            【讨论】:

                              【解决方案23】:

                              您可以使用这段代码来计算 textarea 需要的行数:

                              textarea.rows = 1;
                                  if (textarea.scrollHeight > textarea.clientHeight)
                                    textarea.rows = textarea.scrollHeight / textarea.clientHeight;
                              

                              inputwindow:resize 事件上计算它以获得自动调整大小的效果。 Angular 中的示例:

                              模板代码:

                              <textarea rows="1" reAutoWrap></textarea>
                              

                              auto-wrap.directive.ts

                              import { Directive, ElementRef, HostListener } from '@angular/core';
                              
                              @Directive({
                                selector: 'textarea[reAutoWrap]',
                              })
                              export class AutoWrapDirective {
                              
                                private readonly textarea: HTMLTextAreaElement;
                              
                                constructor(el: ElementRef) {
                                  this.textarea = el.nativeElement;
                                }
                              
                                @HostListener('input') onInput() {
                                  this.resize();
                                }
                              
                                @HostListener('window:resize') onChange() {
                                  this.resize();
                                }
                              
                                private resize() {
                                  this.textarea.rows = 1;
                                  if (this.textarea.scrollHeight > this.textarea.clientHeight)
                                    this.textarea.rows = this.textarea.scrollHeight / this.textarea.clientHeight;
                                }
                              
                              }
                              

                              【讨论】:

                                【解决方案24】:
                                <!DOCTYPE html>
                                <html>
                                <head>
                                    <meta charset="UTF-8">
                                    <title>Textarea autoresize</title>
                                    <style>
                                    textarea {
                                        overflow: hidden;
                                    }
                                    </style>
                                    <script>
                                    function resizeTextarea(ev) {
                                        this.style.height = '24px';
                                        this.style.height = this.scrollHeight + 12 + 'px';
                                    }
                                
                                    var te = document.querySelector('textarea');
                                    te.addEventListener('input', resizeTextarea);
                                    </script>
                                </head>
                                <body>
                                    <textarea></textarea>
                                </body>
                                </html>
                                

                                在 Firefox 14 和 Chromium 18 中测试。数字 24 和 12 是任意的,测试看看哪个最适合你。

                                你可以不使用 style 和 script 标签,但它会变得有点混乱恕我直言(这是旧式 HTML+JS,不鼓励使用)。

                                <textarea style="overflow: hidden" onkeyup="this.style.height='24px'; this.style.height = this.scrollHeight + 12 + 'px';"></textarea>
                                

                                编辑:现代化的代码。将 onkeyup 属性更改为 addEventListener。
                                编辑:keydown 比 keyup 效果更好
                                编辑:使用前声明函数
                                编辑:输入比 keydown 效果更好(thnx @WASD42 & @MA-Maddin)

                                jsfiddle

                                【讨论】:

                                • 这个有一些缺点: 1) Textarea 不会被调整大小然后用户只能用他的鼠标按钮粘贴一些东西; 2) 如果用户将使用键盘 (Ctrl + V) 粘贴某些内容,则仅当他释放 Ctrl 时才会调整文本区域的大小。如果用户按 Ctrl + V 几次,那么 textarea 只会在最后一次之后增长。您也应该添加相同的功能来粘贴、剪切、更改和删除事件。
                                • 所以只需使用input 事件。见stackoverflow.com/a/14029861/1951524
                                • 改进的版本,具有多个 textarea 支持作为单行:document.querySelectorAll('textarea').forEach(function(te){ te.addEventListener("input", function() { this.style.height='24px'; this.style.height=this.scrollHeight+12+'px'; }); });
                                • @Meisner 它更短,但我不会说它是“改进的”。使用匿名函数,无法调用 removeEventListener 并清理您的事件侦听器。当在 forEach 循环中到处创建事件侦听器时,这一点尤其重要。另外,在我看来,可读性远比简洁重要。
                                • 对于其他人和未来的我,请确保设置了 box-sizing: border-box; 属性,否则每个 onInput 事件的 textarea 扩展 4px。我花了大约 3 个小时才发现这是问题所在。
                                【解决方案25】:

                                我推荐 http://javierjulio.github.io/textarea-autosize 的 javascript 库。

                                每个 cmets,添加关于插件使用的示例代码块:

                                <textarea class="js-auto-size" rows="1"></textarea>
                                
                                <script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
                                <script src="jquery.textarea_autosize.min.js"></script>
                                <script>
                                $('textarea.js-auto-size').textareaAutoSize();
                                </script>
                                

                                最低要求的 CSS:

                                textarea {
                                  box-sizing: border-box;
                                  max-height: 160px; // optional but recommended
                                  min-height: 38px;
                                  overflow-x: hidden; // for Firefox (issue #5)
                                }
                                

                                【讨论】:

                                  【解决方案26】:

                                  只需将&lt;pre&gt; &lt;/pre&gt; 与一些样式一起使用,例如:

                                      pre {
                                          font-family: Arial, Helvetica, sans-serif;
                                          white-space: pre-wrap;
                                          word-wrap: break-word;
                                          font-size: 12px;
                                          line-height: 16px;
                                      }
                                  

                                  【讨论】:

                                  • 这不是完整的解决方案。
                                  【解决方案27】:

                                  此代码也适用于粘贴和选择删除。

                                  onKeyPressTextMessage = function(){
                                  			var textArea = event.currentTarget;
                                      	textArea.style.height = 'auto';
                                      	textArea.style.height = textArea.scrollHeight + 'px';
                                  };
                                  &lt;textarea onkeyup="onKeyPressTextMessage(event)" name="welcomeContentTmpl" id="welcomeContent" onblur="onblurWelcomeTitle(event)" rows="2" cols="40" maxlength="320"&gt;&lt;/textarea&gt;

                                  这里是JSFiddle

                                  【讨论】:

                                    【解决方案28】:

                                    这对我有用(Firefox 3.6/4.0 和 Chrome 10/11):

                                    var observe;
                                    if (window.attachEvent) {
                                        observe = function (element, event, handler) {
                                            element.attachEvent('on'+event, handler);
                                        };
                                    }
                                    else {
                                        observe = function (element, event, handler) {
                                            element.addEventListener(event, handler, false);
                                        };
                                    }
                                    function init () {
                                        var text = document.getElementById('text');
                                        function resize () {
                                            text.style.height = 'auto';
                                            text.style.height = text.scrollHeight+'px';
                                        }
                                        /* 0-timeout to get the already changed text */
                                        function delayedResize () {
                                            window.setTimeout(resize, 0);
                                        }
                                        observe(text, 'change',  resize);
                                        observe(text, 'cut',     delayedResize);
                                        observe(text, 'paste',   delayedResize);
                                        observe(text, 'drop',    delayedResize);
                                        observe(text, 'keydown', delayedResize);
                                    
                                        text.focus();
                                        text.select();
                                        resize();
                                    }
                                    textarea {
                                        border: 0 none white;
                                        overflow: hidden;
                                        padding: 0;
                                        outline: none;
                                        background-color: #D0D0D0;
                                    }
                                    <body onload="init();">
                                    <textarea rows="1" style="height:1em;" id="text"></textarea>
                                    </body>

                                    如果你想试试jsfiddle 它从单行开始,仅增长所需的确切数量。单个textarea 是可以的,但我想写一些我会有很多很多这样的textareas 的东西(大约与通常在大文本文档中的行一样多)。在那种情况下,它真的很慢。 (在 Firefox 中它非常慢。)所以我真的想要一种使用纯 CSS 的方法。 contenteditable 可以做到这一点,但我希望它是纯文本的。

                                    【讨论】:

                                    • 确实如此!为你制作了一个 jsfiddle:jsfiddle.net/CbqFv 它现在可以在 Chrome、Firefox 和 IE8 中运行——尽管它在 IE8 中有点小故障。当您增加或减少行数时,它会有点吓人。正如您可能在 jQuery 的 autoresize 插件中看到的那样,他们通过克隆 textarea 来解决这个问题,将其高度设置为 auto 而不是原来的,然后使用它来设置原始的 scrollheight。我在这个更新的小提琴中做到了:jsfiddle.net/CbqFv/2 它解决了 IE 问题,但 Firefox 停止工作。
                                    • @HelenNeely:那就不要使用 id。例如。使用一个类并执行init对该类的所有元素所做的事情。这应该是初学者的任务。
                                    • @DenilsonSá 如果只能假设只使用现代浏览器,那么网络会是一个更好的地方。
                                    • 如果滚动条被卷入到 IE11 中,这将无法正常工作。如果你使用这个小提琴jsfiddle.net/CbqFv 并输入行直到你有一个滚动条你会看到它。有什么想法吗?
                                    • 如果 textarea 靠近页面底部,这将完全中断 - 由于style.height='auto',所有内容都会前后跳动。我怀疑解决方案是添加一个仅用于测量的隐藏兄弟。
                                    【解决方案29】:

                                    jQuery 的解决方案是将 textarea 的高度设置为“auto”,检查 scrollHeight,然后在每次 textarea 更改时调整 textarea 的高度(JSFiddle):

                                    $('textarea').on( 'input', function(){
                                        $(this).height( 'auto' ).height( this.scrollHeight );
                                    });
                                    

                                    如果您正在动态添加文本区域(通过 AJAX 或其他方式),您可以将其添加到您的 $(document).ready 中,以确保所有具有“autoheight”类的文本区域与它们的内容保持相同的高度:

                                    $(document).on( 'input', 'textarea.autoheight', function() {
                                        $(this).height( 'auto' ).height( this.scrollHeight );
                                    });
                                    

                                    在 Chrome、Firefox、Opera 和 IE 中测试和工作。还支持剪切粘贴、长字等。

                                    【讨论】:

                                    • 如果您通过 AJAX 加载带有初始内容的文本区域,您可能需要触发“输入”以确保初始化时高度正确,因此在加载文本区域后,调用 $( 'textarea').trigger('input');
                                    【解决方案30】:

                                    一个更简单、更干净的方法是这样的:

                                    // adjust height of textarea.auto-height
                                    $(document).on( 'keyup', 'textarea.auto-height', function (e){
                                        $(this).css('height', 'auto' ); // you can have this here or declared in CSS instead
                                        $(this).height( this.scrollHeight );
                                    }).keyup();
                                    

                                    // 和 CSS

                                    textarea.auto-height {
                                        resize: vertical;
                                        max-height: 600px; /* set as you need it */
                                        height: auto;      /* can be set here of in JS */
                                        overflow-y: auto;
                                        word-wrap:break-word
                                    }
                                    

                                    只需将.auto-height 类添加到您要定位的任何textarea

                                    在 FF、Chrome 和 Safari 中测试。让我知道这是否对您不起作用,出于任何原因。但是,这是我发现它工作的最干净和最简单的方法。而且效果很好! :D

                                    【讨论】:

                                    • 您是否尝试在编辑后删除文本?文本区域崩溃了吗?
                                    猜你喜欢
                                    相关资源
                                    最近更新 更多
                                    热门标签