键入文本时扩展的 CSS Textarea [重复]

Posted

技术标签:

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

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

【问题讨论】:

没有人想出一个无 jquery 的解决方案来解决这个问题吗? :-( 【参考方案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

以上是关于键入文本时扩展的 CSS Textarea [重复]的主要内容,如果未能解决你的问题,请参考以下文章

当用户键入一些文本时,IE textarea 的宽度会发生变化

在 textarea 上键入时突出显示文本

有没有办法在用户使用 javascript 和 css 键入时设置 textarea 内容的样式?

在 textarea Reactjs 中键入时突出显示文本

更改正在键入的文本的颜色 [重复]

Textarea换行符[重复]