Creating a textarea with auto-resize

2018-12-31 03:29发布

There was another thread about this, which I've tried. But there is one problem: the textarea doesn't shrink if you delete the content. I can't find any way to shrink it to the correct size - the clientHeight value comes back as the full size of the textarea, not its contents.

The code from that page is below:

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 )
    };
}

30条回答
春风洒进眼中
2楼-- · 2018-12-31 03:47

Here is an angularjs directive for panzi's answer.

 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>
查看更多
情到深处是孤独
3楼-- · 2018-12-31 03:48

The jQuery solution is to set the height of the textarea to 'auto', check the scrollHeight and then adapt the height of the textarea to that, every time a textarea changes (JSFiddle):

$('textarea').on( 'input', function(){
    $(this).height( 'auto' ).height( this.scrollHeight );
});

If you're dynamically adding textareas (through AJAX or whatever), you can add this in your $(document).ready to make sure all textareas with class 'autoheight' are kept to the same height as their content:

$(document).on( 'input', 'textarea.autoheight', function() {
    $(this).height( 'auto' ).height( this.scrollHeight );
});

Tested and working in Chrome, Firefox, Opera and IE. Also supports cut and paste, long words, etc.

查看更多
人间绝色
4楼-- · 2018-12-31 03:50

The best solution (works and is short) for me is:

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

It works like a charm without any blinking with paste (with mouse also), cut, entering and it shrinks to the right size.

Please take a look at jsFiddle.

查看更多
唯独是你
5楼-- · 2018-12-31 03:50

The following works for cutting, pasting, etc., regardless of whether those actions are from the mouse, a keyboard shortcut, selecting an option from a menu bar ... several answers take a similar approach but they don't account for box-sizing, which is why they incorrectly apply the style overflow: hidden.

I do the following, which also works well with max-height and rows for minimum and maximum height.

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>

For absolute completeness, you should call the adjust function in a few more circumstances:

  1. Window resize events, if the width of the textarea changes with window resizing, or other events that change the width of the textarea
  2. When the textarea's display style attribute changes, e.g. when it goes from none (hidden) to block
  3. When the value of the textarea is changed programmatically

Note that using window.getComputedStyle or getting currentStyle can be somewhat computationally expensive, so you may want to cache the result instead.

Works for IE6, so I really hope that's good enough support.

查看更多
大哥的爱人
6楼-- · 2018-12-31 03:51

This code works for pasting and select delete also.

onKeyPressTextMessage = function(){
			var textArea = event.currentTarget;
    	textArea.style.height = 'auto';
    	textArea.style.height = textArea.scrollHeight + 'px';
};
<textarea onkeyup="onKeyPressTextMessage(event)" name="welcomeContentTmpl" id="welcomeContent" onblur="onblurWelcomeTitle(event)" rows="2" cols="40" maxlength="320"></textarea>

Here is the JSFiddle

查看更多
旧人旧事旧时光
7楼-- · 2018-12-31 03:52

As a different approach, you can use a <span> which adjusts its size automatically. You will need make it editable by adding the contenteditable="true" property and you're done:

div {
  width: 200px;
}

span {
  border: 1px solid #000;
  padding: 5px;
}
<div>
  <span contenteditable="true">This text can be edited by the user</span>
</div>

The only issue with this approach is that if you want to submit the value as part of the form, you'll have to do so by yourself in JavaScript. Doing so is relatively easy. For example, you can add a hidden field and in the onsubmit event of the form assign the value of the span to the hidden field which will be then automatically submitted with the form.

查看更多
登录 后发表回答