Search code examples
javascripthtmlresizeheighttextarea

Creating a textarea with auto-resize


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

Solution

  • This works for me (Firefox 3.6/4.0 and 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>

    If you want try it on jsfiddle It starts with a single line and grows only the exact amount necessary. It is ok for a single textarea, but I wanted to write something where I would have many many many such textareas (about as much as one would normally have lines in a large text document). In that case it is really slow. (In Firefox it's insanely slow.) So I really would like an approach that uses pure CSS. This would be possible with contenteditable, but I want it to be plaintext-only.