How to Build an Auto-Expanding Textarea jQuery Plugin, Part 1

Auto-Expanding TextareaAuto-expanding textarea elements are popular on sites such as Facebook. The height of the textarea box expands and contracts depending on the quantity of text the user enters. There are several advantages:

  1. Your page design is not dominated by large textarea boxes.
  2. Online forms with several textareas look shorter and less daunting to complete.
  3. The user can see all their text without scrolling.

View an expanding textarea demonstration…

This 3-part tutorial describes how to build an auto-expanding textarea using HTML and a reusable jQuery plugin. By the end of part 3, you will understand how it works and have code to use in your own projects.

The Requirements

Like all good developers, we should thoroughly understand the system requirements:

  1. Any textarea on any page should auto-expand when we require it.
  2. However, some textareas may not require auto-expanding functionality.
  3. We must be able to specify that a textarea height can (a) grow indefinitely, or (b) grow between specific ranges, e.g. use the best height between 50 and 200 pixels.
  4. Our solution should be re-usable on any page we choose.
  5. Progressive enhancement techniques should be used to ensure users without JavaScript can still use a standard textarea box.
  6. The solution should be cross-browser compatible with IE6+, Firefox 2+, Opera, Safari and Chrome.

The Proposal

We will implement the solution as a jQuery plugin. jQuery is primarily used to handle the more mundane aspects of DOM sniffing and event delegation; you could easily re-write the code using another framework.

But how do we know when a textarea should be resized and what height do we use?

First, we can assign a “keyup” event handler to any textarea. This will call a function just after a key has been pressed and the text has been modified.

We can then examine the DOM scrollHeight property. This returns the height of the inner scrolling section, i.e. the height of the text entered by the user. If we set the height of the textarea to the current scrollHeight value, the scrollbar will become obsolete. Unfortunately, scrollHeight is not a W3C recommendation and there are some cross-browser inconsistencies we need to overcome:

  • In Firefox, Safari and Chrome, the scrollHeight is never smaller than the textarea height — even if no text has been added. Therefore, the box would expand but deleting text would not shrink it. We can fix this issue by temporarily setting the textarea height to 0px then applying the real scrollHeight value.
  • Contrary to the Mozilla scrollHeight documentation, Firefox does not appear to include textarea padding whereas Safari 4 and Chrome 2 do. If we have 2px padding at the top and bottom, scrollHeight will be 4px too large in the WebKit browsers and the textarea height would grow indefinitely. Subtracting the padding would break Firefox, so the easiest fix is to apply 0px vertical padding to our expanding textarea elements.
  • In IE and Opera, scrollHeight is quirky. It normally returns the true height of the inner text, however, setting the textarea height to 0px can return incorrect scrollHeight values. Although browser sniffing stinks, I don’t think we have an alternative in this situation. We must ensure IE and Opera never set a textarea height of 0px.

We also need to consider the scrollbar. By default, most browsers only show the textarea scrollbar when it’s required. However, if we leave overflow set to “auto”, the scrollbar would appear as a new line is added then disappear as the textarea height is changed. Setting the overflow to “hidden” will solve flickering scrollbar issues, but that must never be applied to non-expanding textareas or those that have expanded beyond their specified maximum height.

Finally, browser window resizing could be an issue. Fluid web designs could implement a textarea with a percentage-based width: resizing the window would resize the box. Although we can detect window resizing, the event behaves badly in IE and rapidly calls the handler. We can can code around this problem but resizing several textareas could cause the page design to jump around and confuse the user. Therefore, following a resize, we will only adjust the height of a textarea once the user has switched focus to that box.

That’s a lot to take in and there’s more to come! Make yourself a coffee and get ready for part 2

Win an Annual Membership to Learnable,

SitePoint's Learning Platform

  • Joe Zim

    Instead of using the browser sniffing for the 0px problem in IE and Opera, wouldn’t it be more logical to just have it shrink to the height of one line of text, or one pixel or 5 pixels or something like that? There’s no need to go down to 0px whatsoever.

  • http://www.optimalworks.net/ Craig Buckler

    @Joe Zim
    I wish that were the case, but it still doesn’t work. scrollHeight exhibits some very bizarre behaviour in IE and Opera. Shrinking the box significantly(?) below the real scrollHeight value returns seemingly random numbers.

  • http://jacklmoore.com Jack

    I wrote a jQuery plugin that does this (http://jacklmoore.com/autosize/) and came to decide using scrollTop was a better path than scrollHeight, due to how inconsistent is cross-browser. You wouldn’t have to account for padding with scrollTop either.

    Instead of browser sniffing, I featured detected for onpropertychange (IE), and used onkeyup/onkeydown. Otherwise I bound to oninput as it is more encompasses more than keypresses, such as drag/drop, copy/paste, and update on spell-check corrections.