xinglinkedinenvelopebubblesgoogleplusfacebooktwitterfeedgithub

Automatically adjusting the height of a textarea to its content text

16th October 2014 | by Adam Beres-Deak | trick, javascript

While I was working on a simple web based markdown editor I needed something where the users can type their texts. My first thought was to use a DIV with the contenteditable attribute. But it introduced many problems, which I did not want to fight. I only needed something simple and stupid - the good old TEXTAREA.

But also textareas have a big problem: they have a fixed height per default. You can either set the rows attribute to tell how many rows should be displayed, or you can set their style.height properties. But unfortunately there is no auto-height property.

The idea

After every change in the text we have to measure how high the content is. Fortunately there is a method to do it. element.scrollHeight gives us the height of the content, regardless of visible scrollbars. To be able to decrease the size we set the height each time back to zero so that scrollHeight reports the required minimum and not more. E.g. when the user deletes a line.

We also have to calculate the size of the border and outline, so that we don't give any chance for the content to be cut off, or that a scrollbar is shown.

Then we set the style.height property to the calculated height.

To do this every time, we use the oninput event, which is fired every time the text content changes. Contrary to onchange which only fires when the users clicks away.

Show me the code

<textarea data-adaptheight rows="3" cols="40" placeholder="Your input" style="padding: 16px; line-height: 1.5;"></textarea>
<script>
(function() {
    function adjustHeight(textareaElement, minHeight) {
        // compute the height difference which is caused by border and outline
        var outerHeight = parseInt(window.getComputedStyle(el).height, 10);
        var diff = outerHeight - el.clientHeight;

        // set the height to 0 in case of it has to be shrinked
        el.style.height = 0;

        // set the correct height
        // el.scrollHeight is the full height of the content, not just the visible part
        el.style.height = Math.max(minHeight, el.scrollHeight + diff) + 'px';
    }


    // we use the "data-adaptheight" attribute as a marker
    var textAreas = [].slice.call(document.querySelectorAll('textarea[data-adaptheight]'));

    // iterate through all the textareas on the page
    textAreas.forEach(function(el) {

        // we need box-sizing: border-box, if the textarea has padding
        el.style.boxSizing = el.style.mozBoxSizing = 'border-box';

        // we don't need any scrollbars, do we? :)
        el.style.overflowY = 'hidden';

        // the minimum height initiated through the "rows" attribute
        var minHeight = el.scrollHeight;

        el.addEventListener('input', function() {
            adjustHeight(el, minHeight);
        });

        // we have to readjust when window size changes (e.g. orientation change)
        window.addEventListener('resize', function() {
            adjustHeight(el, minHeight);
        });

        // we adjust height to the initial content
        adjustHeight(el, minHeight);

    });
}());
</script>

Demo

Just type in some text and see it for yourself. Initial height is 3 rows.

Tradeoffs

Every keypress causes repaints. Because we set the height of the textarea to 0 and then to the calculated value. This should however be negligible, because most users can only type at most a few characters a second. Therefore it shouldn't cause any noticeable performance drawbacks.

Where to use it for?

There are many cases in which this can be useful. Amongst others:

Do you like it? Do you already use it? Just leave a comment below - the comment box is auto adjusted by default. :)

by Adam Beres-Deak

| Share | Tweet | Share | Share

Latest blog posts

Displaying icons with custom elements 14th October 2015

Plain JavaScript event delegation 26th January 2015

After the first year of blogging - what happened on my blog in 2014? 1st January 2015

Better webfont loading with using localStorage and providing WOFF2 support 18th December 2014

Worth watching: Douglas Crockford speaking about the new good parts of JavaScript in 2014 20th October 2014