A different approach to elastic textareas

I loved elastic textareas since the very first moment I used one (at facebook obviously). They let you save screen real estate while at the same time they are more comfortable for the end user. It’s one of the rare occasions when you can have your UI cake and eat it too!

However, I never liked the implementation of the feature. In case you never wondered how it’s done, let me explain it in a nutshell: All elastic textarea scripts (or at least all that I know of) create a hidden (actually, absolutely positioned and placed out of the browser window) div, copy some CSS properties from the textarea to it (usually padding, font-size, line-height, font-family, width and font-weight) and whenever the contents of the textarea change they copy them to the hidden div and measure it’s dimensions. It might be good enough for facebook, where the styling of those textareas is fairly simple and consistent throughout the site, or any other particular site, but as a generic solution? I never liked the idea.

So, I tried to explore a different approach. As Andrea Giammarchi recently wrote “This is almost intrinsic, as developers, in our DNA: we spot some interesting concept? We rewrite it from scratch pretending we are doing it better!” and I’m no exception (although in this case I don’t think I did it better, I just think it has potential). The basic idea is quite naive, but it works quite well in most browsers (Internet Explorer being the black sheep as usual): Test if the textarea is scrollable, and if so, increase it’s rows attribute and try again. If it’s not scrollable initially, try decreasing it’s rows attribute until it becomes scrollable (and then ++ it).

It works flawlessly on Firefox and quite well on Safari, Chrome and Opera (it just slightly twitches when it enlarges in those). Stupid Internet Explorer though repaints too many times, causing a flicker at the bottom when the user is typing, something really disturbing, so I can’t consider the script anything above experimental at the moment. I’m just posting it in case anyone has an idea of how to fix the aforementioned issues, because apart from those it has quite a few advantages:

  • Should work with any CSS styles
  • No library requirements (unlike all the others I know of)
  • Only 800 bytes minified (2.4KB originally)

So, here it is:

For the record, I don’t think that a script should be needed for things like that. This looks like something that should be handled by CSS alone. We basically want the height of an element to adjust as necessary for it’s contents to fit. We already use CSS for these things on other elements, why not form controls as well?

  • http://probablyprogramming.com Paul Bonser

    I wrote something similar a while back.

    http://probablyprogramming.com/2009/04/24/simple-textarea-auto-resizer/

    It could possibly be made to not flicker in IE by changing the height instead of the rows attribute, possibly with some sort of animation so it happens more smoothly.

    One other thing, I’d suggest listening for a click event as well, because the “paste” event isn’t recognized in several browsers.

  • http://leaverou.me Lea Verou

    Hi Paul,

    Sorry for the late response, I didn’t get an email notification (should look into that)

    Your demo doesn’t work (on firefox 3.5, I don’t have the time to cross-test atm) :-(

    Yeah, most elastic textarea scripts change the height, but this adds an extra layer of complexity to the script: determining the line-height in pixels, taking upon consideration the multiple factors that could affect that on different sites. Also, the reason for that flicker won’t go away: it’s that IE repaints more often than needed. We could just reduce it’s severity, since we could test with smaller increments I guess.

    I did use the click event in the past for such things, but I recently started using the paste event since it’s support is fairly good (for the “buggy” FF implementation, see the details, it just fires it too much, but definitely less times than the click event is fired on a regular user interaction with a common UI!) and the click event is most of the time used for other things, so it makes a script unnecessarily slow (I still use the click event on certain occasions, depends on the particular case).

  • http://probablyprogramming.com Paul Bonser

    Whoops, I guess a recent theme change I made broke some jQuery compatibility code that I wrote for WordPress (var $=jQuery;).

    I’ve fixed it now.

  • http://cameraconcierge.com steve

    re: Internet Explorer.

    All you have to do is, when you detect the need to increase the size of the textarea, INCREASE IT BY 4 LINES OR SO, INSTEAD OF 1!

    Logically, you are doing the same thing a database does, by increasing the size of the .MDF file when data is flowing in. It performs the increase in chunks, and you can do the same, for IE , just use bigger chunks (I know, IE makes me hurl chunks too!! :) )

  • http://leaverou.me Lea Verou

    Happy holidays everyone!

    Steve, that’s a quite clever idea. Have you tried it? I’m afraid the flicker won’t go away, since it will still have to check on every keystroke. Checking is what causes the flicker, not actually enlarging/shrinking it…

  • http://twitter.com/unRob Roberto Hidalgo

    I tried a bunch of different ways that pretty much made IE explode, and finally found your approach. Thanks for sharing!

  • Grant Husbands

    What I do is set overflow to hidden and the height to 1px, measure the scroll-height and make the client-height 1 pixel less than that. Then, after each keypress, I compare the scroll-height and the client-height. Differences of 0px, 1px and >1px tell you different things. The rest is left as an exercise for the reader. Watch out for min-height, though.

  • Pingback: A different Approach to Text Areas - Jennifer Perrin

  • sayan

    Have a look on Jquery elastic demonstration here

  • davidjrobertson

    Try binding to the input event instead of keyup/paste. This eliminates the twitching (at least, it does in chrome).