6

我正在使用该问题的公认答案来构建一个文本区域,该文本区域会随着文本溢出而垂直扩展:

<!DOCTYPE html>
<html>
<head>
<title>autoresizing textarea</title>
<style type="text/css">
textarea {
 border: 0 none white;
 overflow: hidden;
 padding: 0;
 outline: none;
 background-color: #D0D0D0;
 resize: none;
}
</style>
<script type="text/javascript">
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();
}
</script>
</head>
<body onload="init();">
<textarea rows="1" style="height:1em;" id="text"></textarea>
</body>
</html>

在 textarea 的大小比浏览器窗口长之前,它运行良好。此时,每次按下一个键时,窗口的顶部都会跳到文本区域的顶部。你能帮我理解为什么以及如何解决它吗?

一个理想的解决方法是完全阻止页面移动。但是,如果将页面底部与文本区域的底部联系起来更容易,那也可以。

我在 Firefox 21.0 和 Chrome 28.0 中遇到了这个问题:http: //jsfiddle.net/CbqFv/

4

6 回答 6

13

保存scrollLeft,scrollTop值,然后在调整 textarea 大小后恢复它们:

function resize () {
   var scrollLeft = window.pageXOffset ||
   (document.documentElement || document.body.parentNode || document.body).scrollLeft;

   var scrollTop  = window.pageYOffset ||
   (document.documentElement || document.body.parentNode || document.body).scrollTop;

   text.style.height = "auto";
   text.style.height = text.scrollHeight + 'px';

   window.scrollTo(scrollLeft, scrollTop);
}

JSFiddle:http: //jsfiddle.net/losnir/nnkeH/1

于 2013-08-15T22:27:40.063 回答
1

您应该将页面滚动到:滚动条位置 +(调整大小后的文本区域高度 - 调整大小之前的文本区域高度)

这是代码:

    function resize () {
      var scrollLeft = window.pageXOffset ||
      (document.documentElement || document.body.parentNode || document.body).scrollLeft;

      var scrollTop  = window.pageYOffset ||
      (document.documentElement || document.body.parentNode || document.body).scrollTop;

      var prevHeight = text.style.height.slice(0, -2);
      text.style.height = "auto";
      var nextHeight = text.scrollHeight;
      text.style.height = text.scrollHeight + 'px';
      window.scrollTo(scrollLeft, scrollTop + (nextHeight - prevHeight));
    }

或者您可以使用 jquery 执行此操作(基于此答案):

    $('body').on('keyup', 'textarea', function (e) {
      var scrollTop  = $(document).scrollTop();
      var prevHeight = $(this).height();
      $(this).css('height', 'auto');
      var nextHeight = this.scrollHeight;
      $(this).height(nextHeight);
      $(document).scrollTop(scrollTop + (nextHeight - prevHeight));
    });
    $( 'textarea' ).keyup();
于 2014-03-30T04:06:57.823 回答
1

当 textarea 位于可滚动 div 中时,一种接受答案的方法:

function getScrollParent(node) {
    if (node == null) {
        return null;
    }

    if (node.scrollHeight > node.clientHeight) {
        return node;
    } else {
        return getScrollParent(node.parentNode);
    }
}

function resize(){
    // 'this' is the textarea
    const scrollParent = getScrollParent(this);
    const scrollTop = scrollParent ? scrollParent.scrollTop : null;
    const scrollLeft = scrollParent ? scrollParent.scrollLeft : null;

    this.style.height = "auto";
    this.style.height = this.scrollHeight + "px";

    if (scrollParent) {
        scrollParent.scrollTo(scrollLeft, scrollTop);
    }
};
于 2019-03-18T10:52:47.293 回答
1

我的回答是基于接受的答案中的小提琴:textarea 的高度在值增加时增加,但在值减少时不减少

这适用于页面加载和以任何方式更改文本(剪切、粘贴、键入等)时

$('textarea').on('keyup keydown', function () {
var $this = $(this);
var initialHeight = $this.height();

$this
    .height(initialHeight - 40)
    .height($this[0].scrollHeight + 20);}).trigger('keyup');

我获取初始高度的原因是 textarea 不必跳到 1 或任何其他静态数字来触发 scrollHeight 的值。(据我了解,这是导致屏幕更改滚动的原因,因为文本框设置为该静态高度(通常为 1)然后扩展)我将 20 添加到 scrollHeight 的原因是因为有时 scrollHeight 会关闭 1 或 2px 并且文本看起来在底部聚集在一起。所以为了给它更多的空间,我个人添加了 20 个。

于 2020-03-26T13:26:48.307 回答
1

发现这是迄今为止最好的解决方案,结合了 Adam Beres-Deak 和 @losnir 的代码,得出了以下结果。

迄今为止最有用的:

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 textAreas = [].slice.call(document.querySelectorAll('textarea[data-adaptheight]'));
    textAreas.forEach(function(el){
        function resize(){
            var scrollLeft = window.pageXOffset ||
                (document.documentElement || document.body.parentNode || document.body).scrollLeft;
            var scrollTop = window.pageYOffset ||
                (document.documentElement || document.body.parentNode || document.body).scrollTop;
            el.style.resize = "none";
            el.style.overflow = 'hidden';
            el.style.boxSizing = el.style.mozBoxSizing = 'border-box';
            el.style.height = "auto";
            el.style.height = el.scrollHeight + 'px';
            window.scrollTo(scrollLeft, scrollTop);
        }
        observe(el, 'input', resize);
        resize();
    });
}
init();
<textarea data-adaptheight style="padding: 7px;width: 100%;display: block;" rows="1" cols="40" placeholder="Your input">
</textarea>

于 2021-02-05T21:02:57.037 回答
1

Re losnir 的回答,在 Firefox Desktop (88) 中,似乎window.pageXOffset返回一个非整数值,但将其window.scrollTo()四舍五入为整数值。因此,如果初始window.pageXOffset值的小数部分为 0.5 或更多,那么在每次更改文本时,textarea 框都会向下移动少量。其他浏览器可能会发生这种情况。解决方案是将滚动变量声明为四舍五入,然后在第一次更改文本时有一个小的偏移,之后所有的值都将是整数,并且不会发生进一步的偏移。这给出了:

function resize () {
    var scrollLeft = Math.round(window.pageXOffset ||
                (document.documentElement || document.body.parentNode || document.body).scrollLeft);
   var scrollTop  = Math.round(window.pageYOffset ||
                (document.documentElement || document.body.parentNode || document.body).scrollTop);

   text.style.height = "auto";
   text.style.height = text.scrollHeight + 'px';

   window.scrollTo(scrollLeft, scrollTop);
}
于 2021-04-23T16:24:58.507 回答