Media Temple Hosting

Textarea Auto Resize

Textarea Auto ResizeOn a current project, I was trying to find a way to auto-resize a textarea according to some content that would be loaded in dynamically via Ajax. I didn’t know the height of the content and the textarea element doesn’t resize naturally like other HTML elements, so I needed to update the height of the element with JavaScript each time the content changed.

It seemed like a simple task. After doing a search to see what types of plugins and scripts were floating around to do this, the examples I found seemed a little overly complex. While most solutions seemed to incorporate some complex math calculations, I thought of a better way.

Using a Hidden Clone Element

A <div> element will naturally stretch to fit the height of its content (assuming no floats or absolutely positioned elements are involved). So to get the height of the textarea, I just need to do the following:

  • Grab the content loaded into the textarea
  • Create an invisible clone div
  • Give the clone the same width and typographical properties as the textarea
  • Place the content into the clone
  • Get the height of the clone
  • Apply the height of the clone to the height of the textarea

The Code

One of the keys to this solution is the CSS. As mentioned, the invisible clone needs to have the same typographical properties as the textarea. Not only does this include stuff line font-size and font-family, but also the white-space and word-wrap properties of the clone need to be set to mimic what happens inside the textarea.

First here’s the CSS for the textarea:

textarea {
    width: 500px;
    min-height: 50px;
    font-family: Arial, sans-serif;
    font-size: 13px;
    color: #444;
    padding: 5px;

.noscroll {
    overflow: hidden;

Take note that I’ve added a separate class with overflow: hidden, to prevent scrollbars from appearing. Normally this would not be a good thing to add to a textarea element, but because I’ll be resizing it with JavaScript, it’s fine. This class will be added to the textarea with JavaScript, to ensure that if JavaScript is turned off, the textarea will scroll normally.

Here is the CSS I’ll be applying to the hidden clone element:

.hiddendiv {
    display: none;
    white-space: pre-wrap;
    width: 500px;
    min-height: 50px;
    font-family: Arial, sans-serif;
    font-size: 13px;
    padding: 5px;
    word-wrap: break-word;

A quick break-down: First, I set it to display: none because I don’t want it visible to the user. I believe this should be fine for screen readers, because I don’t want it read out to them either. If anyone has a better solution for hiding it for assistive devices, let me know.

I’ve also set the white-space property to a value of “pre-wrap”. This ensures that lines will wrap correctly, but everything else gets pre-formatted. I’ve also set the width to be equal to the textarea, and duplicated a few typographical properties. In both examples, I’m giving the clone and the textarea a min-height so it will always start out at a standard, usable height.

Now for the JavaScript (which is using jQuery, sorry):

$(function() {
    var txt = $('#comments'),
        hiddenDiv = $(document.createElement('div')),
        content = null;

    hiddenDiv.addClass('hiddendiv common');


    txt.on('keyup', function () {

        content = $(this).val();

        content = content.replace(/\n/g, '
'); hiddenDiv.html(content + '
'); $(this).css('height', hiddenDiv.height()); });​ });

This code assumes we’re targeting a single textarea element on the page. If you need this to affect more than one element, then just change the first line inside the function that defines the element we’re working with.

I’m dynamically changing the height based on jQuery’s keyup event. You could easily change this to respond to an Ajax request instead, if you happen to be loading the content that way.

Using keyup, however, is a good solution because it’s the most likely reason that you’ll want to auto-resize a textarea — user-entered data.

What About IE6-8?

I almost didn’t write this article, because the code wasn’t working at all in IE6-8. The reason for this had to do with the poor way IE handles grabbing content using innerHTML. So after I had written this simple solution that seemed to work in all the newer browsers, I came across this jQuery plugin. That solution uses the exact same method that I’m using (the cloned element), and it worked (mostly) in IE.

So the line that I borrowed from that example that (mostly) fixed mine in IE was:

// fixes the IE innerHTML problem
content = content.replace(/\n/g, '<br>');

But even after adding this line, there was still an issue: Long, unbroken strings of text wouldn’t affect the height of the textarea (which isn’t a big problem, really). A simple fix was adding word-wrap: break-word to the CSS for the clone element.

Bugs? Problems?

Like the other solutions floating around, this could easily be turned into a plugin. In that case, I’d have to add a little more jQuery so that the characteristics of the clone element aren’t dependent on the CSS. Also, if the width of the textarea is fluid, then you’d have to use jQuery to grab that, and then apply it to the clone.

The solution I linked to in the previous section is just about perfect — you just need to add the word-wrap fix that I mentioned.

For a demo, you can view my JSFiddle using the link below. Just be sure to hit the “run” button before you test it. Let me know if you find any problems with it.

Update (Aug. 14/2012) The demo link above now points to an updated version with some of the fixes suggested in the comments along with some CSS improvements.

89 Responses

  1. This would make for a fantastic jQuery plugin! Kudos.

    • Yeah, that was one of the ones that I found when initially researching this. The one bonus of James’s is that it actually works on input elements too, for expanding the width as you type.

      But I’m hesitant to recommend a plugin for this solution that’s 275 lines long. Maybe I’m missing something here, but my solution in this example is about 20 lines and if converted to a plugin could probably be around 30-40 max.

      There’s also an option on SitePoint:

      Which is about 60 lines, commented — so much more reasonable I think.

      I initially said I couldn’t think of a reason to auto-expand an input but on second thought it would be useful to have an input element start out small then expand as you type (for long email addresses or whatever).

  2. Thank you this trick help me a lot.

  3. I like the idea, clever. Just for the sake of another option, here’s one that is fairly short and library free that works really efficiently I think:

    • Nice, I didn’t know about that one. Usually the ALA stuff doesn’t go under my radar. Obvious drawback for that one is the lack of support for IE6/7, but certainly a good option since old IE support is becoming less and less of an issue.

  4. Brian Nickel:

    One problem I’ve noticed is that if you press “enter” to expand to a new line, the text area will be slightly scrolled, most likely because “<br>” at the end of a <div> doesn’t do anything. I overcame this with the following:

    hiddenDiv.html(content + ' ');

    If you don’t want the text to scroll briefly every time you reach a new line, you could do the following:

    hiddenDiv.html(content + ' <br> ');

  5. Nice Article. i am learning Web designing, i was just searching On “resizing” i found this article, which is really useful that Auto Resize, it will gonna save more time n Progress in this way! thanks for this very nice explanation n writing worth reading :)

  6. Jon:

    This is seriously awesome! I can’t wait to use it on my blog.

  7. Great post, I enjoyed trying it out.

  8. Realy great article. Thank you, i try it :)

  9. kaeku:

    Hey! I had to fix the same issue at work just last week. I solved it by getting the scroll-height of textarea and expanding it by the difference that was determined by subtracting the actual height from the scroll-height.

    It would look kind of like this:

    var el = $(this);
    setTimeout(function() {
        var height = $(el).height();
        var scrollHeight = $(el).prop('scrollHeight');
        $('#log').text('height: ' + height + ' scrollHeight: ' + scrollHeight);
        if (scrollHeight > height)
    }, 1);

    After that, you just bind the function to the desired events

  10. I’d rather use bind('input', .... instead of keyup as there more ways to enter text than just by keyboard ;)
    Moreover, instead of using div and replacing newlines with <br>, you could use <pre>.

    It would also be a great idea to set opacity of textarea to 0 and then apply some kind of syntax highlighting to the text-containing element (I’m thinking of binding highlighting to blur event).

    My code (from 1st Nov) can be found here:

    • Just as an FYI:

      The “input” event only works in newer browsers, so although this seems like a good solution, it won’t work in IE6-8, so for now I’ll stick with “keyup”.

  11. Filip Bech-Larsen:

    You could argue it makes sence to either add textarea{ resize: none; } to your css, or add something that turns the feature off when the user uses the manual resize of pulling the corner of the textarea. Maybe your script could be only to resize bigger, and not smaller? I, for one, like the illlusion of overview therefore often resizing textareas to be really large. If that cancelled after each key-up that would make me very tired :-D But great idea with the cloned element.

  12. Mc Benny:

    A difficulty of your solution in case of several textareas or if you want to turn it to a generic system is the way you prepare your clone: by applying fixed styles. I encountered the problem a few years ago and I solved it by just getting the styles of the targetted textarea involved in presentation and putting them to the cloned element on the fly:

    	'default':	$(this).val()
    	,'w':		$(this).width()
    	,'ttransform':	$(this).css('text-transform')
    	,'lheight':	$(this).css('line-height')
    	,'wspacing':	$(this).css('word-spacing')
    	,'ffamily':	$(this).css('font-family')
    	,'fsize':	$(this).css('font-size')
    	,'fweight':	$(this).css('font-weight')
    	,'lspacing':	$(this).css('letter-spacing')
    	,'wrap':	$(this).css('word-wrap')
    ^t		.after('<div />')
    		position:		'absolute'
    		,left:			'-9999em'
    		,width:			$(tArea).data('w')
    		,'text-transform':	$(tArea).data('ttransform')
    		,'line-height':		$(tArea).data('lheight')
    		,'word-spacing':	$(tArea).data('wspacing')
    		,'font-family':		$(tArea).data('ffamily')
    		,'font-size':		$(tArea).data('fsize')
    		,'font-weight':		$(tArea).data('fweight')
    		,'letter-spacing':	$(tArea).data('lspacing')
    		,'word-wrap':	$(tArea).data('wrap')

    By the way, you don’t need any padding on your cloned element.

    My function is about 70 lines of code and also accepts multiple classes to target the textareas, if any is interested.

    • You’re right about the padding on the clone. I’m in the process of updating the code so I’ll apply that style only to the parent. I’ll also look into grabbing the styles dynamically, but that would complicate the JS unnecessarily I think.

  13. This should become default functionality in browsers. I get sick of 3-line textareas.

  14. Thanks for your article, i’m beginning in CSS and it looks like its a real challenge to get good at it. Anyway i want to so i’ll bookmark your site! ;)

  15. Tim:

    Awesome work, love keeping it simple!

  16. I was developing and needed a quick solution that I’ll optimize later.

    Call this function on whatever you want.
    id can be class tag or id

    function adjustTextarea(id){
    	var txt = $(id),
    	hiddenDiv = $(document.createElement('div')),
    	content = null;
        content = txt.val();
        content = content.replace(/\n/g, '');
        txt.css('height', hiddenDiv.height());
    	txt.bind('keyup', function() {
    	    content = txt.val();
    	    content = content.replace(/\n/g, '');
    	    txt.css('height', hiddenDiv.height());

    I copied this exact snippet into my console and made your textarea adjust lol.

  17. Ben Demboski:

    I just wrote a jQuery plugin for auto-sizing textareas using this approach. I call it Yet Another Auto Resizer (YAAR), and you can find it here: I’d love to hear what folks think of it.

    • Hey, Ben. Good idea! I should really do this myself when I get some time.

      I’m trying to get your script to work, but I can’t. Does it require certain CSS set on the textarea? Here’s my fiddle:

      I must be doing something wrong… ? I also don’t see a live demo linked on your GitHub repo. Maybe throw a fiddle link on there so people can see a working version.


  18. mike:


  19. Thanks mate, this helped. All I noticed is that errors occur is you do not clone the css styling applied on the textarea exactly same on the div. It did not work pretty great at the first go albeit when I applied the same padding, borders etc – worked!

  20. Expanding textareas, awesome.

  21. I added little fix enter. When user hit enter then there was no go to new line. See improved version:

    • I don’t see a problem with hitting enter on the original version. Can you explain what it is you’re trying to fix with that? Maybe I don’t understand..? What browser are you using?

      • Try to typing something and then hit enter, enter, enter until you will go at very bottom of textarea. Just before the end of textarea. Then hit anter and you will see cursor on the next line, but textarea is not stretched until you’ll not hit any key.

        Tested on IE9 (9.0.8112.16421) and Firefox 13.0.1. Probably the same thing is on other browsers, but not tested.

        • Hmmm. I don’t see a huge difference. The major difference I see is that the first line of text (before hitting enter) gets pushed slightly up, getting cut off momentarily.

          But it seems like a minor thing. Anyhow, I’ll take a closer look and maybe I’ll update it with your fix, pending some further testing. Thanks.

  22. the double backslash

    content = content.replace(/\\n/g, '');
    • You’re right, I’ll fix that. Although it still works either way, apparently regexp statements using “/n” are supposed to escape the backslash and thus use double backslash. Thanks.

    • Changed my mind. For some reason, this breaks it in IE8. I don’t know enough about regular expressions but I’ll have to stick with single slash for now.

  23. I just came across this other solution, which you can see here:

    The code is very small, and from what I can see, it works everywhere, including IE7/8. The only problem in IE seems to be the fact that the textarea always shrinks down to a single line when you click out of it after deleting anything you’ve typed.

    But if you don’t care about IE<9 then this might be a good choice. Credit for this goes to "user1432124" who gave this answer on a StackOverflow thread about auto-resizing textarea elements.

    • Wes:

      I found one major benefit to this code – less lag. If typing quickly, this solution works very well. I’ve found that Louis’ code can lag 20 or more characters.

      • Hmm… that’s odd. I don’t have that problem at all.

        But even if that’s true, it’s somewhat irrelevant, because the only time the element auto-expands is when you create a new line (either by reaching the end and wrapping, or else hitting “enter”), so it really shouldn’t lag.

        Can you create a screencast showing this happening in comparison to the other code? You can use for a quick easy screencast to share. Thanks.

        • Wes:

          Can’t do a screencast since it doesn’t show when fingers stop hitting the keys. I must admit that this only happens when a VERY fast typist (85+wpm transcriptionist) gets going and it quickly catches up when input stops. You can simulate by just hitting keys as fast as you can (be sure include a spcae) and not worry about it being real words.

  24. Wes:

    Any downsides to using scrollHeight? Seems to work for me. This will maintain the minimum of 50 and expand/contract as needed:

    txt.bind('keyup', function() {
           var sh = this.scrollHeight;
  = sh < 50 ? "50px" : sh+"px";
    • According to this page:

      scrollHeight is supported in IE8+, so if someone needs support below that, then it might not work.

      But… I tested it in IE8 in IE7 mode, and it seems to work exactly the same way as IE8. I also tested in IE7 on IETester, and it works the same way. So I’m not sure what to think.

      So my guess is, yeah, this seems to be the better script simply because it’s so small and does pretty much the exact same thing as mine and any of the other really long scripts available online for this.

    • Ah… this page explains:

      It says:

      In Internet Explorer earlier than version 8, [scrollHeight] retrieves the height in physical pixel size, while from version 8, it returns the height in logical pixel size… The height is calculated in the default pixel size in Internet Explorer before version 8 even if the current pixel size in the document is different. From Internet Explorer 8 … the height is calculated in the current pixel size.

      So I think it’s safe to use, because that seems to be a not-too-significant edge case problem at most.

      • Wes:

        I’ve noticed that it works fine while adding – but removing text seems to act weird – only seems remove about a pixel per event.

  25. Wes:

    I am using a triggered keyup event (as referenced earlier in this great blog) and it works fine except for an area that is not shown when the page loads – it is located in collapsed tab. Any ideas for getting that to pre-expand?

    Thanks also for your incredible response time. I am amazed.

    • Wes:

      Sorry, I jumped the gun with this request – I thought it would be difficult to solve but the jquery tabs docs ( had a solution – I trigger the keyup when the tab is shown via the tabs show event. It fires for all selected elements, even those on the tabs just hidden, but that shouldn’t be much of a problem.

      $( "#tabs" ).tabs(
        show: function(event, ui) { $(".expand").trigger('keyup'); }
  26. bacr:

    hi, I would like to take the width of a parent element, so I did some modifications, but for any reason this is working in IE8 but is not working in IE7(it expands horizontally). Do you have an idea why is this happening ?

    (function ($) {
          autoresize: function () {
             return this.each(function () {
                hiddenDiv = $(document.createElement('div'));
                content = null;
                hiddenDiv.addClass('hiddendiv common');
                $(this).on('keyup', function () {
                   myParent = $(this).parent('td');
                   content = $(this).val();
                   content = content.replace(/\n/g, '');
                   hiddenDiv.html(content + "");
                   hiddenDiv.css('width', myParent.width());
                   $(this).css('height', hiddenDiv.height());


    • Can you post this on a JS Fiddle, so it’s working in IE8, and then I can debug it to see what’s wrong in IE7? Thanks.

      • bacr:

        Sure no problem.
        To tell you the true, I have a table and inside the table I have asp textbox, so the parent of this textbox is a td element. The issue is that when I enter data in the textbox at some point the textbox begin to expand horizontally. This happen in IE7, IE8 works ok.

        • bacr:

          Sorry, you should you change the framework to JQuery to get it work. Thanks.

        • I don’t see the problem that you’re referring to. I tested in IE8 natively, and that’s fine.

          Then I tested in IE8 in “IE7 mode” and that works the same way. I also used IETester to test in IE7, and I got the same result, it works exactly the same as in IE8.

          What kind of IE7 are you testing in? I can’t test IE7 natively. Are you using some standalone thing?

          Can you record a screencast using, showing what is happening in IE8 compared to IE7? That would be helpful, so I can see what you’re talking about. Thanks.

  27. A one little problem, what if I turned off javascript?

    • Then it just works like a regular textarea, no expanding. That shouldn’t be a problem in most cases. You could allow the textarea’s natural size to be set via CSS (for no js) then change it with JS, and allow auto-expanding. You could also use Modernizr and use the no-js class.

  28. Kvet:

    Why you don`t use

    $(...).bind('input propertychange', ...)


    It works great for me!

  29. Tobias:

    too complicated.

    $(‘.editnote’).live(‘keyup’, function(e) {
    var height = $(this).height();
    var scrollheight = $(this).scrollTop();

    if((scrollheight + height) > height) {
    $(this).height(height + 16 + ‘px’);


  30. mayumi:

    Thanks you!!

  31. tugelsikile:

    thanks, been looking for this :D

  32. HGN:

    Thank you Louis, I finally found something useful! The other one in the web scrapped from Facebook has conflicts with other versions of jquery, yours is perfect!

  33. Made it work on all textareas that have .auto-resize on them.

  34. Rong:

    This is cool, but it misses all situations:
    (1) The user could type texts into the textarea with keyboard.
    (2) The user could paste texts into the textarea with shortcut for keyboard.
    (3) The user could paste texts into the textarea with mouse.

    Unfortunately, the current code does not cover all three situations well.

    • As far as I can see, only the third one in that list doesn’t work, and I’m not sure why not. It seems like it’s very rare that a user would paste with their mouse only, but I suppose it’s an edge case that could be handled.

      I’ll make a note of it and see if I can improve it. Thanks.

    • Here you go, problem solved:

      Now all three should work correctly. It was just a matter of changing the event from “keyup” to “input”. I don’t know if this works in all browsers, however. I only tested latest versions.

      • chenar:

        it not work in ie10

      • arjun menon:

        it would be also good to add a scrollbar after reaching a certain height. otherwise, it would just keep on growing like king kong

        • arjun menon:

          also, why isnt the rows value not working

        • Well, that is the point, that it grows as much as is typed. If you want a scrollbar, then there’s no point using this plugin, just set a height in the CSS. :)

          And as for rows/cols: In the main demo I can see “rows” working fine until you start typing, then the box goes back to the size based on number of lines. Cols doesn’t work because the CSS overrides it with a width. Just remove that and it should work.

          But I don’t think you need a “rows” value, again, for the same reason mentioned before, because the rows are dependent on the lines typed. If you want a min-height that it starts out as, then just set that in the CSS.

  35. sudha:

    its not working when i use the same code in my jsp. its not autoresizing the text box. its hiding first linesof text when i type more lines in my textbox. its not autoresizing.can any one help me.

    body {
    margin: 20px;

    p {
    margin-bottom: 14px;

    textarea {
    color: #444;
    padding: 5px;

    .txtstuff {
    resize: none; /* remove this if you want the user to be able to resize it in modern browsers */
    overflow: hidden;

    .hiddendiv {
    display: none;
    white-space: pre-wrap;
    word-wrap: break-word;
    overflow-wrap: break-word; /* future version of deprecated ‘word-wrap’ */

    /* the styles for ‘commmon’ are applied to both the textarea and the hidden clone */
    /* these must be the same for both */
    .common {
    width: 500px;
    min-height: 50px;
    font-family: Arial, sans-serif;
    font-size: 13px;
    overflow: hidden;

    .lbr {
    line-height: 3px;

    /*global document:false, $:false */
    var txt = $(‘#comments’),
    hiddenDiv = $(document.createElement(‘div’)),
    content = null;

    hiddenDiv.addClass(‘hiddendiv common’);


    txt.on(‘keyup’, function () {

    content = $(this).val();

    content = content.replace(/\n/g, ”);
    hiddenDiv.html(content + ”);

    $(this).css(‘height’, hiddenDiv.height());


    • You’re going to have to provide a live link that I can look at, then I can see what the problem is. The code alone will not help much, especially if you just copied it from my post.

  36. + 1 to jquery autoResize plugin … just works

  37. Anonymous:

    Thanks for the post!

    Change these 2 lines:

    content = content.replace(/\n/g, '');  
    hiddenDiv.html(content + '');

    to this:

    content = content.replace(/\n/g, ' <br> ');
    hiddenDiv.html(content + ' <br> ');

    And the text stops jumping on entering a new line and the resizing is smooth.

  38. Rizaldi:

    nice trick… Thanks for sharing…

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.