【问题标题】:CSS Textarea that expands as you type text [duplicate]键入文本时扩展的 CSS Textarea [重复]
【发布时间】:2011-06-24 15:58:13
【问题描述】:

我有一个文本区域,用户可以在其中输入文本。默认情况下,它的高度为 17px。但是,如果用户插入大量文本,我希望文本区域相应扩展。有没有办法用 CSS 做到这一点?提前致谢!!

【问题讨论】:

  • 没有人想出一个无 jquery 的解决方案来解决这个问题吗? :-(

标签: javascript jquery html css textarea


【解决方案1】:

仅靠 CSS 无法做到这一点。试试 autogrow jquery 插件。 https://github.com/jaz303/jquery-grab-bag/blob/master/javascripts/jquery.autogrow-textarea.js

您还可以在此处查看自动增长演示 http://onehackoranother.com/projects/jquery/jquery-grab-bag/autogrow-textarea.html

它轻巧且易于使用。这是它是如何完成的。定义您的文本区域 ID。在</body> 之前包含jquery js 文件。然后在script标签之间,发出jquery命令$("#txtInput").autoGrow();

<body>
    <textarea id="txtInput"></textarea>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script> 

<script>
    $("#txtInput").autogrow();
</script>
</body>

【讨论】:

  • 为什么 javascriptly 链接会带我去 bet365.com!!
  • $('#textInput').autoGrow(); 应该是$(#txtInput).autogrow();
【解决方案2】:

我知道这有点晚了,但我不得不说有一种方法可以使用 &lt;div&gt;contenteditable 属性来模拟所需的行为。

.textareaElement {
  width: 300px;
  min-height: 17px;
  border: 1px solid #ccc;
  max-height: 150px;
  overflow-x: hidden;
  overflow-y: auto;
}
&lt;div class="textareaElement" contenteditable&gt;&lt;/div&gt;

只需设置您的最小和最大高度,使用适当的溢出值,您就拥有功能齐全的纯 CSS 扩展文本框,这也得到了很好的支持。

【讨论】:

  • 很好的解决方案,因为我只关心 Chrome 支持。谢谢!
  • 这是一个很好的解决方案!唯一复杂的是,当您按下回车键时,它会将所有新文本放入&lt;div&gt; 块中。所以innerHTML变成了一个文本节点,后面跟着一堆&lt;div&gt;s。
  • 我认为这也是一个很好的解决方案,但是如果您对文本进行任何操作,contentEditable 很快就会变成一场灾难,因为它的处理方式非常不同并且文档也不是很好。如果您只想要一个简单的文本输入,是的,但请注意有很多带有可编辑内容的曲线球。
【解决方案3】:

这个 jQuery 插件非常棒: http://www.jacklmoore.com/autosize

我已经测试了一堆,这是迄今为止最好的。还给出了一个使用 CSS 过渡效果的例子,非常漂亮。

【讨论】:

  • 我同意这是目前最好的解决方案。最重要的是,它修复了这个错误:当 textarea y-overflow 被隐藏时,Chrome/Safari 不会重新排列文本以占用通过移除滚动条而提供的空间。 标记为的 autogrow jquery 插件答案没有这个修复。
【解决方案4】:

**请注意,这与上面 Woody 的回答非常相似,但想对其进行一些扩展并提供一个运行代码示例,因为 Stack 允许我们嵌入它们。

在阅读了所有这些并尝试了几个插件之后,我发现这些都没有像我希望的那样工作。我使用 jquery 完成了以下操作,但可以通过抓取填充值而不是使用内部高度来轻松地使用 javascript 完成:

  • 在 CSS 中设置 textarea 的最小高度
  • 将溢出设置为隐藏以进行垂直滚动(我只是想垂直展开)
  • 如果滚动高度高于高度 + 填充 (innerHeight),则在每个 keyup 事件上将高度设置为滚动高度减去填充。
  • 如果滚动高度不高,我将高度重新设置为 1,然后将高度设置为滚动高度减去填充(以缩小高度)。如果您最初不重置为较小的高度,则滚动高度不会缩小。

$(function() {
  $('#myTextArea').on('input keyup paste', function() {
    var $el = $(this),
        offset = $el.innerHeight() - $el.height();

    if ($el.innerHeight() < this.scrollHeight) {
      // Grow the field if scroll height is smaller
      $el.height(this.scrollHeight - offset);
    } else {
      // Shrink the field and then re-set it to the scroll height in case it needs to shrink
      $el.height(1);
      $el.height(this.scrollHeight - offset);
    }
  });
});
#myTextArea {
  width: 250px;
  min-height: 35px;
  overflow-y: hidden;
}
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<textarea id="myTextArea" placeholder="Hit enter a few times, it should expand"></textarea>

【讨论】:

  • 这对我来说非常适合“keyup paste input”——除非我从数据库加载数据。当我点击它时,textarea 会展开,但正如最初显示的那样,它只会显示第一行。我的 JQuery 是“按需”,所以基本上不存在。我尝试添加一些事件,例如'ready','load' 和更多,但似乎没有任何效果。有人有什么建议吗?
  • 可能有更优雅的方式来执行此操作,但您始终可以手动触发 keyup 事件,以便在您从数据库加载数据后运行上述代码 -- $('#test') .keyup();如果它是在服务器端呈现的静态页面,其中包含数据库数据,则可以将 keyup 事件放在 jquery 就绪函数中,以便在加载 jquery 和其他库后运行 -- $(function() { $('#测试').keyup(); });
  • 非常感谢您的回复。我已经尝试过 keyup 没有成功 - 可能是因为我在 ListView 中有许多文本框实例,并且我在 JS 中按类识别它们。我用 $(".ExpandableText").keyup();并尝试使用单引号。还没有人抱怨初始尺寸。不过只是时间问题。
【解决方案5】:

您不需要插件。这适用于任何大小、高度或行大小的 textarea,并且仅在内容超出 textarea 时才有效。首先将目标文本区域上的溢出设置为隐藏并将大小调整为无,然后将以下功能添加到要自动增长的文本区域中。它不仅会在用户键入时增加文本区域的大小,而且还会在用户删除内容时自动缩小。

$('textarea').on('paste input', function () {
    if ($(this).outerHeight() > this.scrollHeight){
        $(this).height(1)
    }
    while ($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))){
        $(this).height($(this).height() + 1)
    }
});

它通过测量 textarea 的滚动高度是否大于外部高度来工作,只有当文本超过 textarea 可以容纳的文本时才会出现这种情况 - 并且它会考虑边框大小以提高准确性。使用粘贴和输入意味着它只会在用户物理更改文本区域的值时增加,而不是在他们按下任何键时。它很小,但是当有人按下箭头键或其他东西时,文本区域不应该增长。

为那些没有 Javascript 的人添加一个 No JS 选项来重新启用溢出和调整大小可能是明智的,否则他们会被一个小盒子卡住。

【讨论】:

  • 之后没有减少。
  • 只要你不要忘记包含 jQuery 库,它就可以正常工作!!! Yarin jsfiddle 没有它。但是一旦你在 options 中选择了 jQuery 1.9.1,之后一切都好。
  • @ekashking 我没有得到那个结果。
  • 它可以工作,但由于某种原因,在我的包含许多表格和文本区域的复杂页面上,它非常慢,有时在按下 Enter 键后会暂停一两秒。
【解决方案6】:

为此使用 JavaScript。

此脚本在每次击键后检查文本区域的长度(来自here 的copypasta):

  <textarea name="x" onKeyUp="SetNewSize(this);" cols="5" rows="4"></textarea>
    <script language="javascript">
    function SetNewSize(textarea){
      if (textarea.value.length > 5){
        textarea.cols = 50;
        textarea.rows = 50;
      }  else{
         textarea.cols = 10;
         textarea.rows = 15;
      }
    }
  </script>

【讨论】:

    【解决方案7】:

    有点晚了,但这对我来说就像一个魅力,它在 jquery 中:

    此文本区域的限制高度为 200 像素,起始高度为 22 像素。填充有助于将文本保持在一个好的位置,但是,我们必须根据字体的大小来调整权重。

    在另一个问题中也有类似的答案,但这个更完整一些。

    $('textarea').each(function () {
      // Do something if you want
    }).on('input', function () {
      this.style.height = 'auto';
      // Customize if you want
      this.style.height = (this.scrollHeight - 30) + 'px'; //The weight is 30
    });
    textarea{
        padding: 7px;
        width: 50%;
        height: 22px;
        max-height: 200px;
        resize: none;
        overflow-y: scroll;
        font-size: 16px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div>Textarea:</div>
    <textarea></textarea>

    【讨论】:

    • 是的!该代码基本上依赖于scrollHeight。如果你看css,你会发现“overflow-y:scroll”,每次textarea溢出时,文本会下降,scrollHeight会增加文本的高度......所以它的作用是增加额外的高度滚动到textarea的高度...简单来说就是把里面文字的高度加到textarea的高度上。
    【解决方案8】:

    在您键入时扩展文本区域

    在 textarea 中输入内容以查看效果

    <script>    
    function increseRows(selector)
    {
        $(selector).attr("rows", $(selector).val().split("\n").length+1||2);
    }
    </script>
    

    【讨论】:

    • ||是什么意思
    • @Manish,它只是逻辑“OR”运算符,但在这种情况下,如果计算的长度以某种方式计算为 false,则它被用于默认为 2 行。
    【解决方案9】:

    我使用以下(当然是 jQuery):

    $(function () {
        'use strict';
        $("textarea").on('change keyup paste input', function () {
            $(this).attr("rows", Math.max($(this).val().split("\n").length || 1, $(this).attr("rows") || 1));
            $(this).css("width", $(this).css("width"));
        }).trigger('change');
    });
    

    请注意,它响应各种事件,仅增加行数(即不减少),触发初始更改(例如,在浏览回具有大量行的表单时调整大小)

    【讨论】:

    • 这不起作用。它将 NaN 作为四个绑定事件中的任何一个的行。如果 textarea 上没有换行符或没有“行”属性,则您正在尝试使用“未定义”进行数学运算。因此,这仅在实际有新行可以使用时才有效......这永远不会,因为当您在该字段中执行任何操作时,绑定事件会将行设置为 NaN,从而防止任何进一步的修改。
    • 你是对的,textarea 必须有一个“rows”属性才能使我的原始代码工作。我添加了一个守卫(` || 1`)来满足这一点。
    • 如果将Math.max改为Math.round,删除文本后textarea也会缩小。
    【解决方案10】:

    这似乎更有效率并且可以处理最大高度

    $(ctrl).on('paste input', function () {
        var dyLineHeight, dyMax, dyHeight;        
        if ($(this).outerHeight() > this.scrollHeight)
            $(this).height($(this).outerHeight() - parseFloat($(this).css("borderBottomWidth")) - parseFloat($(this).css("borderTopWidth")));
        dyLineHeight = Math.max(3, parseInt($(this).css("line-height")));
        dyMax = parseInt($(this).css("max-height"));
        while ($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth")))
            {
            dyHeight = $(this).height();
            if (dyHeight >= dyMax)
                break;
            $(this).height(dyHeight + dyLineHeight)
            }
    });
    

    【讨论】:

      【解决方案11】:

      我一直在寻找纯 js 解决方案(项目中没有 jquery)并最终编写自己的解决方案。它非常快,没有兼容性问题,并且不需要额外的库。

      需要注意的一个细节是你需要在新字符出现之前放大框,但在字符消失后缩小框(按退格键或删除后)

      function updateSize(e) {
        let text = e.target.value + String.fromCharCode(event.keyCode);
        e.target.rows = text.split(/\r\n|\r|\n/).length;
      }
      
      function keyDownUpdateSize(e) {
        if (event.keyCode != 8 && event.keyCode != 46)
          updateSize(e);
      }
      
      function keyUpUpdateSize(e) {
        if (event.keyCode == 8 || event.keyCode == 46)
          updateSize(e);
      }
      
          
        
      document.querySelector(selector_to_your_textarea).addEventListener("keydown", keyDownUpdateSize);
      document.querySelector(selector_to_your_textarea).addEventListener("keyup", keyUpUpdateSize);

      【讨论】:

        【解决方案12】:

        老问题,但你可以这样做:

        html:

        <textarea class="text-area" rows="1"></textarea>
        

        jquery:

        var baseH; // base scroll height
        
        $('body')
            .one('focus.textarea', '.text-area', function(e) {
                baseH = this.scrollHeight;
            })
            .on('input.textarea', '.text-area', function(e) {
                if(baseH < this.scrollHeight) {
                    $(this).height(0).height(this.scrollHeight);
                }
                else {
                    $(this).height(0).height(baseH);
                }
            });
        

        这样,自动调整大小将应用于任何具有“文本区域”类的文本区域。删除文本时也会缩小。

        jsfiddle:

        https://jsfiddle.net/rotaercz/46rhcqyn/

        【讨论】:

          【解决方案13】:

          使用 Javascript。 textarea 的行为类似于 textarea,并且您想要更改它(您希望它的行为类似于 div),因此您必须修改您想要的行为。

          这是我几个月前在某个地方找到的解决方案,但无法再次找到。它可能添加了我自己的味道:

          标记:

          <div>
            <textarea class='my-textarea' />
            <div className='my-textarea autogrow' style="display: 'none';" />
          </div>
          

          样式:

          .my-textarea {
            border: 1px solid #bbb;
            font-family: Helvetica;
            font-size: 15px;
            overflow: hidden;
            padding: 5px;
            resize: none;
          }
          
          // Needs same styles as the textarea except overflow.
          .autogrow {
            overflow: auto !important;
          }
          

          将此事件侦听器获取到 textarea 的 change 事件:

          function growTextarea(e) {
            const { value } = e.target
            const textarea = e.target
            const { grower } = this
          
            grower.style.display = 'block'
            grower.innerHTML = value.length ? value : 'x'
            textarea.style.height = grower.offsetHeight + 'px'
            grower.style.display = 'none'
          }
          

          它是如何工作的?基本上,div 的扩展是您希望 textarea 的扩展表现的样子。因此,您正在制作一个与 textarea 样式相同的 div,并将 textarea 的值放入 div 中。然后获取 div 的高度并将 textarea 的高度设置为该高度。

          使用 display none 和 block,div 出现和消失,因此您可以测量它的高度。你永远不会在浏览器中真正看到它。

          希望这对你有用!

          附:我使用 React,所以我不得不将我的解决方案更改为与框架无关。所以它可能有错误或语法错误。例如。您可能需要查询文档才能找到种植者 div。

          【讨论】:

            【解决方案14】:

            如果您使用的是 Angular2/4,那么有一个很棒的 directive here 可以工作。

            当您将数据动态加载到文本区域时,请参阅问题列表以获取解决方法。除了这个问题,它适用于 ReactiveForms 和模板表单。

            作为参考,这是指令代码:

            import { Input, AfterViewInit, ElementRef, HostListener, Directive} from '@angular/core';
            
            @Directive({
                selector: 'textarea[autosize]'
            })
            
            export class Autosize implements AfterViewInit {
            
                private el: HTMLElement;
                private _minHeight: string;
                private _maxHeight: string;
                private _lastHeight: number;
                private _clientWidth: number;
            
                @Input('minHeight')
                get minHeight() { 
                  return this._minHeight;
                }
                set minHeight(val: string) {
                  this._minHeight = val;
                  this.updateMinHeight();
                }
            
                @Input('maxHeight')
                get maxHeight() {
                  return this._maxHeight; 
                }
                set maxHeight(val: string) {
                  this._maxHeight = val;
                  this.updateMaxHeight();
                }
            
             @HostListener('window:resize', ['$event.target'])
                onResize(textArea: HTMLTextAreaElement) {
                  //Only apply adjustment if element width had changed.
                  if (this.el.clientWidth === this._clientWidth) return;
                  this._clientWidth = this.element.nativeElement.clientWidth;
                  this.adjust();
                }
            
             @HostListener('input',['$event.target'])
              onInput(textArea: HTMLTextAreaElement): void {
                this.adjust();  
              }
            
              constructor(public element: ElementRef){
                this.el = element.nativeElement;
                this._clientWidth = this.el.clientWidth;
              }
            
              ngAfterViewInit(): void{
                // set element resize allowed manually by user
                const style = window.getComputedStyle(this.el, null);
                if (style.resize === 'both') {
                        this.el.style.resize = 'horizontal';
                    }
                else if (style.resize === 'vertical') {
                        this.el.style.resize = 'none';
                }
                // run first adjust
                this.adjust();
              }
            
              adjust(): void{
                // perform height adjustments after input changes, if height is different
                if (this.el.style.height == this.element.nativeElement.scrollHeight + "px") return;
                this.el.style.overflowX = 'hidden';
                this.el.style.height = 'auto';
                this.el.style.height = this.el.scrollHeight + "px";
              }
            
              updateMinHeight(): void{
                // Set textarea min height if input defined
                this.el.style.minHeight = this._minHeight + 'px';
              }
            
              updateMaxHeight(): void{
                // Set textarea max height if input defined
                this.el.style.maxHeight = this._maxHeight + 'px';
              }
            
            }
            

            【讨论】:

              【解决方案15】:
              function autoExpand(field) {
              
                  // Reset field height
                  field.style.height = 'inherit';
              
                  // Get the computed styles for the element
                  var computed = window.getComputedStyle(field);
              
                  // Calculate the height
                  var height = parseInt(computed.getPropertyValue('border-top-width'), 10)
                               + parseInt(computed.getPropertyValue('padding-top'), 10)
                               + field.scrollHeight
                               + parseInt(computed.getPropertyValue('padding-bottom'), 10)
                               + parseInt(computed.getPropertyValue('border-bottom-width'), 10);
              
                  field.style.height = height + 'px';
              
              };
              

              为我工作

              https://gomakethings.com/automatically-expand-a-textarea-as-the-user-types-using-vanilla-javascript/

              【讨论】:

                【解决方案16】:

                var textarea = document.querySelector('textarea');
                textarea.addEventListener('keydown', autosize);             
                function autosize(){
                  var el = this;
                  setTimeout(function(){
                    el.style.cssText = 'height:auto; padding:0';    
                    el.style.cssText = 'height:' + el.scrollHeight + 'px';
                  },0);
                }
                textarea{   
                  overflow:hidden; 
                  padding:10px;
                  width:250px;
                  font-size:14px;
                  margin:50px auto;
                  display:block;
                  border-radius:10px;
                  border:6px solid #556677;
                }
                <textarea rows="6" >
                CSS Textarea that expands as you type text
                rows Specifies the visible number of lines in a text area and cols	Specifies the visible width of a text area
                </textarea>

                【讨论】:

                • 请在代码中也提供一些解释。
                • 默认文本区域 6 行即 6 行。当您/用户可以在文本区域内自动键入文本时,文本区域的高度会增加。当您按下键时 autosize() 功能触发
                • 如果您添加额外的 jquery 插件其他人则浪费您的时间,应用程序加载时间可能很长​​span>
                • 请尝试为我正常工作。您可以根据自己的要求尝试和修改。这个非常简单的方法
                【解决方案17】:

                这对我有用

                $(".textarea").on("keyup input", function(){
                    $(this).css('height', 'auto').css('height', this.scrollHeight+(this.offsetHeight - 
                    this.clientHeight));
                 });
                

                【讨论】:

                  【解决方案18】:

                  为 React Angular 或 Vue 提出了简单的解决方案。

                  您只需要将textarea 包裹在div 中,将textarea 的内容写入div 并给textarea 绝对位置、高度和宽度100%(不要忘记相对在div 上的位置)。

                  所以现在divtextarea 完美叠加,当div 因为里面的文字而扩展时,textarea 会自动这样做。

                  不要忘记设置完全相同的填充、字体大小和字体系列。

                  【讨论】:

                  • 我会说这更 hackier
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-07-03
                  • 2010-12-25
                  • 1970-01-01
                  • 2014-12-08
                  • 2017-11-04
                  • 1970-01-01
                  • 2011-03-17
                  相关资源
                  最近更新 更多