simple textarea auto-resizer

Today I was having issues with a textarea resizer (a hacked-up version of SmartArea) that I had been using for a while in a work project. It was working fine for textareas of a certain width, but it got less and less useful as the textareas got less wide, not wrapping lines until it already had scrollbars for a word or two.

It seemed to me that it needn’t be as complex as it was, so I decided to try and write my own, and here’s what I came up with:

    function growTextArea(e) {
        if (!this.rows || this.rows < 1) this.rows = 1;
        while (this.clientHeight >= this.scrollHeight && this.rows > 1) this.rows -= 1;
        while (this.clientHeight < this.scrollHeight) this.rows += 1;
    }

A working example, embedded using jQuery:

    $('#example-resizing-textarea')
        .keyup(growTextArea).keyup();

Type some text in here:

Compatibility

This works for me in Firefox, IE6, IE7, Chrome and Chromium, Safari (for Windows, testing in a Windows VM along with the IEs and Chrome), and Opera 9.62. As you may have noticed I’ve avoided using any JS-library or browser-specific code, so this should work equally well with jQuery, Prototype, or with no library at all.

IE actually gives incorrect values for scrollHeight, but that is easily made up for by using “this.clientHeight >= this.scrollHeight” in the first while loop rather than “this.clientHeight == this.scrollHeight”

Minimum and Maximum rows

If you want to set a minimum and maximum height, it takes a little more work:

    function sizeTextArea(min, max) {
        return function(e) {
            if (!this.rows || this.rows < min) this.rows = min;
            while ((this.clientHeight >= this.scrollHeight 
                    && this.rows > 1 && this.rows <= max) 
                   || this.rows > max) this.rows -= 1;
            while ((this.clientHeight < this.scrollHeight 
                    || this.rows < min) 
                   && this.rows < max) this.rows += 1;
            if (this.rows == max
                && this.clientHeight < this.scrollHeight) this.style.overflow = 'auto';
            else this.style.overflow = 'hidden';
        }
    }

Another example, limited to having between 4 and 8 rows:

    var sizer48 = sizeTextArea(4, 8);
    $('#example-resizing-textarea')
        .keyup(sizer48).keyup();

Type some text in here, too:

Possible modifications could include using pixel sizes instead of changing the “row” attribute and animating the resizing.

This could easily be packaged into a plugin for jQuery or Prototype, and I might just do that, but right now it’s getting late, so I’m going to sleep instead.

blog comments powered by Disqus