Jan Miksovsky’s BlogArchive2011 AboutRSSJSONContact

Control of the Week: Facebook-style AutoSizeTextBox

It’s nice to have multi-line text boxes resize to fit their contents. The native HTML <textarea> tag, which creates a multi-line text box, gives the text box a fixed height. (Chrome and Firefox will let you manually resize a textarea, which helps, but the resizing isn’t done for you.) A fixed height text box never feels like it’s the right height: if you don’t have any text to enter, a tall box is too big, and if want to actually enter a block of text, you always find yourself wishing the box were bigger.

Auto-sizing feels like a missing feature of web forms. Many forms need to let the user type in lines of text into a text box, and since the size of that text can vary, it seems to make sense to start out with a small text box, then grow the text box when necessary. HTML has had form support since at least HTML 2.0, so it’s surprising this feature is still not standard. For comparison, Microsoft Word’s form support has had auto-sizing text boxes for years.

I think the first solid implementation of a web auto-sizing text box was on Facebook, which offers you such a text box to enter a status update:

 

Facebook Status Box

 

Facebook's design varies from week to week (and user to user), but at the time I took the image above, the text box started out tall enough to contain three lines of text. As the user types more, the text box grows in size:

 

Facebook Status Box (with more text)

 

Key aspects

Usage

See AutoSizeTextBox in the QuickUI Catalog for a working, reusable implementation.

The default height of an AutoSizeTextBox is set to accommodate two lines of text. This suggests to the user that they’ll have ample room to type. As they begin to type on the second line, a third will automatically be created for them. As a result, they’ll never feel like they’re running out of room. In tight spaces, this minimum height can be overridden to produce an AutoSizeTextBox that’s only one line tall when empty.

Implementation notes

I’m not aware of a pure CSS solution to this problem; the variety of ways to implement an auto-sizing text box all require some degree of JavaScript. A while back I posted a solution on StackOverflow that, at its core, leaves most of the layout calculations to the browser. In this approach, the textarea and a hidden element are both placed inside a containing div. I'd originally used a div for the hidden element, but realized that using a <pre> (preformatted) element would automatically preserve line breaks and white space.

The hidden pre is set to use visibility: hidden, which tells the browser to layout the control as normal, but leave the pre invisible. When the user types in the textarea, a small bit of JavaScript simply copies the contents of the textarea into the hidden pre element. As the pre gets bigger, it forces the containing div to become bigger, which in turn makes the textarea grow. The textarea ends up as big as the hidden copy of the text (plus an extra line), which gives us the effect we want.

The most finicky bit of the implementation deals with letting the control work with different font sizes. During initialization, the font of the overall control is copied over to the textarea and hidden pre so that the text metrics of the two elements will be the same. This operation has to wait until the control is actually in the DOM so that any relevant styles will have been applied.

Moreover, the initialization logic needs to know the line height of the text in the textarea. Unfortunately, if line-height has not been explicitly set, WebKit and IE report the line-height as “normal”, instead of giving us an actual measurement we can use. So the control calculates an approximate line-height by applying a constant factor to font-size. This approximation means that the text box height can be off by a pixel or so in WebKit and IE.