Textarea Auto Grow

I have seen instances where I'm on a form on a website and there is some mechanism by which the textarea automatically grows to fit what I'm typing. I've also seen this not work too well, and eventually half the bottom line is cut off or the bottom of the textarea has expanded further than it needs to.

A while ago a super simple solution to this popped into my head. And today I happened to need just such a solution. So, I wrote up a vary small JavaScript function to add to our utility library.

Here is the code.

<script type="text/javascript">
function autoGrowField(f) {
   var scrollH = f.scrollHeight+'px';
   if(f.style.height != scrollH){
      f.style.height = scrollH;
   }
}
</script>
Example Use:
<textarea name="txt"
    style="width:500px; height:45px;"
    onkeyup="autoGrowField(this)">
Little bit of text</textarea>

Where I have this implemented in our application, that simple, 6-line function worked. It is dead simple. When you type a character, it runs the function "autoGrowField". The function asks a simple question: Has the scrollHeight* exceeded the height of the field? If it has, then it just adjusts the height of the field to the scrollHeight.

But, if you have a small textarea or you paste in large amounts of text there are some issues. One issue is: If the textarea does not have a vertical scroll bar all the time, when you type the character that causes it to need to scroll, then when the scroll-bar is added, it takes up about 18 pixels of space and causes even more line wrapping to occur. Then, the function runs, sees the scrollHeight (with the extra wrapping), and sets the height higher than it needs to be. Then the scrollbar disappears leaving a textarea that is unnecessarily long.

I tried out a couple of ways to fix this. The first was to run the same logic twice. So, if the textarea had grown tall enough to need a scrollbar, set the height to the total scrollable height. Then see if the scrollHeight was taller than height. If so, adjust the height again. That caused the textarea to jump around a bit. The second was to just make sure the textarea always has a scrollbar (but not the drag-handle). This is what I'll be sticking with for now. You can see that code below.

<script type="text/javascript">
function autoGrowField(f) {
   /* Make sure element has scroll bar to prevent jumpy-ness */
   if (f.style.overflowY != 'scroll') f.style.overflowY = 'scroll';
   /* Now adjust the height */
   var scrollH = f.scrollHeight;
   if( scrollH > f.style.height.replace(/[^0-9]/g,'') ){
      f.style.height = scrollH+'px';
   }
}
</script>
Example Use:
<textarea name="txt"
    style="width:200px; height: 45px;"
    onkeyup="autoGrowField(this)">
Little bit of text</textarea>

*scrollHeight: The entire height of an element (including areas hidden with scrollbars)

Updated (May 4 2010):

Based on Justin's suggestion below, I made some final changes to this script. I also added a max height argument (just for fun). The changes get rid of having a scroll-bar or scroll-handle. Not having either of these makes it visually smoother. Below is an updated example.

<script type="text/javascript">
function autoGrowField(f, max) {
   /* Default max height */
   var max = (typeof max == 'undefined')?1000:max;
   /* Don't let it grow over the max height */
   if (f.scrollHeight > max) {
      /* Add the scrollbar back and bail */
      if (f.style.overflowY != 'scroll') { f.style.overflowY = 'scroll' }
      return;
   }
   /* Make sure element does not have scroll bar to prevent jumpy-ness */
   if (f.style.overflowY != 'hidden') { f.style.overflowY = 'hidden' }
   /* Now adjust the height */
   var scrollH = f.scrollHeight;
   if( scrollH > f.style.height.replace(/[^0-9]/g,'') ){
      f.style.height = scrollH+'px';
   }
}
</script>
Example Use:
<textarea name="txt"
style="width:200px; height: 45px; overflow-y:hidden;"
onkeyup="autoGrowField(this,300)">
Little bit of text</textarea>

Comments
Justin Carter's Gravatar You could also style the textarea so that it doesn't have scrollbars (set overflow to auto / hidden) couldn't you? No doubt each browser will behave slightly differently though :)
# Posted By Justin Carter | 5/4/10 3:07 AM
Chris Phillips's Gravatar Justin,

You are correct. This is why blogging is worth it. You just made this better.

If you init the textarea to a style of "overflow-y:hidden;" and change second script example to make sure that the overflowY is 'hidden', then the scroll-handle no longer flashes right before it adds another line.

Thanks for the idea.
# Posted By Chris Phillips | 5/4/10 11:46 AM
Justin Carter's Gravatar Cool stuff Chris, glad I could contribute :)
# Posted By Justin Carter | 5/4/10 12:17 PM
Pete's Gravatar Excellent work, you should add a autoShrinkFunction too
# Posted By Pete | 5/4/10 8:13 PM
Chris Phillips's Gravatar Pete,

The first one does 'auto-shrink' it. Or more accurately, it 'auto-size's it. The first example just makes sure that the height of the textarea is exactly what it needs to be. I didn't really like that behavior (textarea shrinking when I first type in an empty one). So, you'll see in the final script that it does a numeric value comparison on the scrollheight and only expands when it needs to.

And this was really just an exercise to stimulate my synapses. Any of you can take this script and use it anyway you want with or without credit.
# Posted By Chris Phillips | 5/5/10 9:17 AM
Paul Janssen's Gravatar Doest work at all in Safari it seems
# Posted By Paul Janssen | 2/25/11 5:44 AM
Esa Ajo's Gravatar Excellent work.

If you call from window.onload following function, your texareas will be autosize also on when loading page:

function resizeTextAreas() {
   var objects = document.getElementsByTagName("textarea");
   for(var i=0;i<InvalidTags.length;i++){
      objects[i].onkeyup();
   }
}
# Posted By Esa Ajo | 7/14/11 6:10 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.6.002.