创建具有自动调整大小的文本区域

IT技术 javascript html resize height textarea
2021-02-08 04:54:55

还有一个关于这个的线程,我已经试过了。但是有一个问题: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 )
    };
}
6个回答

一个完整而简单的解决方案

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

以下代码将起作用:

  • 在按键输入上。
  • 带有粘贴的文本(右键单击和 ctrl+v)。
  • 带有剪切文本(右键单击和 ctrl+x)。
  • 带有预加载的文本。
  • 在所有 textarea (多行文本框)站点范围内。
  • 使用Firefox (经过 v31-67 测试)。
  • 使用Chrome (经过 v37-74 测试)。
  • 使用IE (经过 v9-v11 测试)。
  • 使用Edge (经过 v14-v18 测试)。
  • IOS Safari
  • 使用安卓浏览器
  • 使用 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>

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

这对我有用(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上尝试它, 它从一行开始,并且只增长所需的确切数量。一个stextarea没问题,但我想写一些东西,我会有很多很多这样的textareas(大约和一个大文本文档中通常有几行一样多)。在这种情况下,它真的很慢。(在 Firefox 中它非常慢。)所以我真的想要一种使用纯 CSS 的方法。这可以用contenteditable,但我希望它是纯文本的。

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

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/

在 Chrome 40 Win 8.1 中,在比视口长的文本上像疯了一样跳来跳去。导致它非常无法使用。
2021-03-15 04:54:55
使用多个事件来为广泛的场景工作 $('textarea.auto-resize').on('change cut paste drop keyup', function(){...})
2021-03-24 04:54:55
不完全确定,但没有它,文本区域会增长太多。我认为这与元素 scrollHeight 的计算方式有关。
2021-03-25 04:54:55
这很好,但我会添加overflow-y: hidden;到 css 中以防止发生调整大小时滚动条短暂闪烁。
2021-04-03 04:54:55
按住回车(换行)会导致滚动。直到松开按键,尺寸才会调整。
2021-04-08 04:54:55
<!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)

提琴手

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

对我来说最好的解决方案(有效且简短)是:

    $(document).on('input', 'textarea', function () {
        $(this).outerHeight(38).outerHeight(this.scrollHeight); // 38 or '1em' -min-height
    }); 

它就像一个魅力,没有任何闪烁的粘贴(也用鼠标),剪切,输入并缩小到正确的大小。

请看一下jsFiddle

此解决方案的有用调整是还隐藏垂直滚动条(在 jsFiddle 中看到,此处未提及),您可以使用内联样式(style="overflow:hidden")或适当的样式来执行此操作: textarea {overflow: hidden;}
2021-03-12 04:54:55
了不起!!!单线交易!愚蠢的问题我可以在调整大小时添加动画吗?像文本框一样轻轻地调整大小而不是跳转到大小?
2021-03-26 04:54:55
@user2513846 看起来多行编辑的设计是不可能的。我做了一个动画文本区域大小的例子:jsfiddle.net/yk2g333e正如你所知,文本光标在行或插入符号的 and 处向下移动,所以如果此时没有停顿,则没有任何动画。但是暂停对用户来说会很烦人。
2021-04-05 04:54:55
@user2513846 但是,在 textarea 末尾多出一个空行,就有可能获得流畅的动画效果:jsfiddle.net/p23erdfr
2021-04-07 04:54:55
@Gregor Simončič 是的,特别是对于长文本 - 它可以正确计算 textarea 目标高度。而且,为了精确计算,将outerHeight设置为0会更好。
2021-04-07 04:54:55