Создание текстовой области с автоматическим изменением размера - PullRequest
309 голосов
/ 18 января 2009

Был другой поток об этом , который я пробовал. Но есть одна проблема: 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 )
    };
}

Ответы [ 38 ]

4 голосов
/ 23 июня 2011

Я использовал следующий код для нескольких текстовых областей. Хорошо работает в Chrome 12, Firefox 5 и IE 9, даже с действиями удаления, вырезания и вставки, выполненными в текстовых областях.

<!-- language: lang-html -->
<style type='text/css'>
textarea { border:0 none; overflow:hidden; outline:none; background-color:#eee }
</style>
<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>
<script type='text/javascript'>
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
</script>
4 голосов
/ 01 мая 2017

Следующее работает для вырезания, вставки и т. Д., Независимо от того, выполняются ли эти действия с помощью мыши, сочетания клавиш, выбора параметра в строке меню ... несколько ответов используют аналогичный подход, но не учитывают для определения размера ящика, поэтому они неправильно применяют стиль overflow: hidden.

Я делаю следующее, что также хорошо работает с max-height и rows для минимальной и максимальной высоты.

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. При изменении атрибута стиля textarea display, например, когда он переходит от none (скрытый) к block
  3. Когда значение textarea изменяется программно

Обратите внимание, что использование window.getComputedStyle или получение currentStyle может быть несколько вычислительно дорогим, поэтому вы можете вместо этого кэшировать результат.

Работает для IE6, так что я действительно надеюсь, что это достаточно хорошая поддержка.

4 голосов
/ 24 марта 2018

В качестве другого подхода вы можете использовать <span>, который автоматически регулирует его размер. Вам нужно будет сделать его редактируемым, добавив свойство 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 скрытому полю, которое затем будет автоматически отправлено с формой.

2 голосов
/ 24 мая 2012

Я знаю короткий и правильный способ реализации этого с помощью jquery. Никаких дополнительных скрытых div не требуется и работает в большинстве браузеров

<script type="text/javascript">$(function(){
$("textarea").live("keyup keydown",function(){
var h=$(this);
h.height(60).height(h[0].scrollHeight);//where 60 is minimum height of textarea
});});

</script>
2 голосов
/ 19 июня 2011

Немного исправлений. Отлично работает в Opera

  $('textarea').bind('keyup keypress', function() {
      $(this).height('');
      var brCount = this.value.split('\n').length;
      this.rows = brCount+1; //++ To remove twitching
      var areaH = this.scrollHeight,
          lineHeight = $(this).css('line-height').replace('px',''),
          calcRows = Math.floor(areaH/lineHeight);
      this.rows = calcRows;
  });
2 голосов
/ 11 ноября 2014

Не знаю, упоминал ли кто-нибудь об этом, но в некоторых случаях можно изменить высоту с помощью атрибутов строк.

textarea.setAttribute('rows',breaks);

Демо

2 голосов
/ 28 ноября 2018

Вы можете использовать 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>
2 голосов
/ 29 августа 2017

Вот директива 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>
1 голос
/ 01 июня 2013

Некоторые ответы здесь не учитывают заполнение.

Если у вас есть максимальная высота, которую вы не хотите пересекать, это сработало для меня:

    // obviously requires jQuery

    // element is the textarea DOM node

    var $el = $(element);
    // inner height is height + padding
    // outerHeight includes border (and possibly margins too?)
    var padding = $el.innerHeight() - $el.height();
    var originalHeight = $el.height();

    // XXX: Don't leave this hardcoded
    var maxHeight = 300;

    var adjust = function() {
        // reset it to the original height so that scrollHeight makes sense
        $el.height(originalHeight);

        // this is the desired height (adjusted to content size)
        var height = element.scrollHeight - padding;

        // If you don't want a maxHeight, you can ignore this
        height = Math.min(height, maxHeight);

        // Set the height to the new adjusted height
        $el.height(height);
    }

    // The input event only works on modern browsers
    element.addEventListener('input', adjust);
1 голос
/ 09 мая 2019

моя реализация очень проста, подсчитайте количество строк на входе (и минимум 2 строки, чтобы показать, что это текстовая область):

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

полный рабочий пример со стимулом: https://jsbin.com/kajosolini/1/edit?html,js,output

(и это работает, например, с ручкой изменения размера браузера)

...