On 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;
txt.addClass('txtstuff');
hiddenDiv.addClass('hiddendiv common');
$('body').append(hiddenDiv);
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.

This would make for a fantastic jQuery plugin! Kudos.
James Padolsey has an excellent plugin for this: https://github.com/padolsey/jQuery.fn.autoResize
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:
http://www.sitepoint.com/build-auto-expanding-textarea-1/
Which is about 60 lines, commented — so much more reasonable I think.
Edit:
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).
Thank you this trick help me a lot.
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:
http://www.alistapart.com/articles/expanding-text-areas-made-elegant/
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.
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> ');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 :)
This is seriously awesome! I can’t wait to use it on my blog.
Great post, I enjoyed trying it out.
Realy great article. Thank you, i try it :)
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:
After that, you just bind the function to the desired events
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
blurevent).My code (from 1st Nov) can be found here: http://pastebin.com/j9LbTQb8
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”.
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.
I’m going to remove the manual resize ability, and then allow developers to change the CSS if they want.
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:
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.
Keep it real [simple] in this rap game:
link to jsbin: http://jsbin.com/adebol
Simpler, no jQuery, shorter easier javascript, quicker updating, no height calculation, reflow resize via css. You’re welcome ::bows:: -ck
Doesn’t work in IE6-8.
You’re welcome. :)
LIES! works fine in ie8. ::shakes head at you for not telling the truth::
as for ie6-7 support,
change
white-space: pre-wrap;to
white-space: pre;using an ie < 7 specific hack…
like so:
jsbin: http://jsbin.com/uvebag
…so i’ll say it again. You’re welcome!
And due to the invalidity of your prior statements, I expect a written apology… preferably with some mother effin smiley face stickers… ;-)
-ck
That’s strange, because I was looking at it in “edit” mode on JSBin, and it doesn’t work in IE8 there, but it does work in preview mode.
That is strange, as it should work the same, since it’s just an iframe.
So, you’re right, sorry for the hasty reply, but I was looking at the code view in Chrome then copied and pasted the URL into IE8. Thanks.
I have to admit, after examining this code a little closer, this really is a great solution. The only minuscule drawback is the extra div, but you could easily add that via JavaScript instead, and then the HTML would be clean. But I’m fine with it either way.
Kudos on this, great thinking — and great that you can take advantage of as much CSS as possible without needing a JS library or much JS at all.
Thanks for the kind words. It’s only a slight evolution of your concept, at its core its still using the “use a DIV to measure text size”. And I agree if I were packaging this as a plugin or in a library the DIV would get added dynamically on the target textarea/input via
$('textarea#foo').autoResize({ vertical: true, horizontal 400 });or something to that effect, and you would obviously use targeted css class names… I just wanted represent the concept as simply as possible. Hats off for doing the leg work on the original concept. -ck
Thank you very much. IT Work. ^^
This should become default functionality in browsers. I get sick of 3-line textareas.
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! ;)
Awesome work, love keeping it simple!
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
I copied this exact snippet into my console and made your textarea adjust lol.
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: https://github.com/bendemboski/jquery-yaar. 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:
http://jsfiddle.net/zSHYh/
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.
Thanks!
excellent
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!
Expanding textareas, awesome.
I added little fix enter. When user hit enter then there was no go to new line. See improved version: http://jsfiddle.net/fGNNT/872/
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.
That was what I mean. Thanks.
I believe this will be fixed after adding an extra <br> element after the content that’s inserted. I’m also going to reduce the line-height on the <br> element so it’s not such a large gap.
Hello there!
I am new to JS and CSS, and I need to use your script in a project I am currently working on. Essentially, it achieves what I need, however, I need to apply it on ALL the textareas that are in the page and not a single one only.
I read your hint: “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.”
and hence tried to change the selector from id-wise to class-wise as follows:
var txt = $(‘.comments’)
and tagged all the textareas with the “comments” class, but it works on the first textarea element it encounters only. Perhaps I am doing something wrong? Help please!
Dina, you’re right. Looks like I didn’t think it through properly.
Here’s a corrected version, with multiple textareas:
http://jsfiddle.net/jRpNM/
I will eventually updated the post to fix this bug. Thanks for pointing this out!
Thank you Louis, it works perfectly!
It’s great that you are still keen to improve your script, and its my pleasure to report more bugs :D
I encountered an initialization problem. To be specific, if the Texarea already contains some text when the document is loaded and if this text exceeds the TA’s bounds, the TA does not expand. Of course this is because the script is bound to the keyup event only and so far when loading, no keys are released.
How the script works now makes sense if the assumption is that users are only allowed to type “after” the document has been loaded and the script bound to the component, but not allowed to have a “pre-populated” text area.
At the moment I solve this by simply repeating what you do in the bind function but without binding anything, just doing the copy into div, get height, copy back the height thing. I feel though its not the cleanest approach :D
Do you have an idea how to do it better and cleaner? can one bind the same function to the same variable but with two different events? if yes, what event-type would correspond to “onload”? (I know google is my friend, I already googled and tried out some stuff, but unfortunately I am still too new to this to spot why it doesnt work).
Thanks again!
Dina
Good question, Dina! This is good stuff, because it’s helping me to refine the script, as I’m planning to eventually code it as a real jQuery plugin.
To do what you want with previously existing text, you could do it a couple of ways, but I think the shortest way is to force the keyup event using “trigger”. Here it is:
http://jsfiddle.net/jRpNM/1/
Notice the fields now have different amounts of default text and they resize accordingly.
Oh, and that reminds me, another thing you should do is change the “bind” handler to “on”, the latter of which is now deprecated in the latest jQuery. So the updated code with both fixes looks like this:
http://jsfiddle.net/jRpNM/2/
Perfect!
I am actually using your script in a totally different context. I’m trying to style a textarea’s scrollbar by hiding it, auto-expanding the TA as a user types and wrapping it up in a div where its much easier to style this div’s scrollbar. Now the the div is in control of panning through its child element, the TA.
Still some problems to go, but at least now they are less :)
If I find other bugs, I’ll let you know. Thanks!
Dina
the double backslash
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.
I just came across this other solution, which you can see here:
http://jsbin.com/idemad/2/edit
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.
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 screenr.com for a quick easy screencast to share. Thanks.
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.
Any downsides to using scrollHeight? Seems to work for me. This will maintain the minimum of 50 and expand/contract as needed:
According to this page:
https://developer.mozilla.org/en-US/docs/DOM/element.scrollHeight
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:
http://help.dottoro.com/ljbixkkn.php
It says:
So I think it’s safe to use, because that seems to be a not-too-significant edge case problem at most.
I’ve noticed that it works fine while adding – but removing text seems to act weird – only seems remove about a pixel per event.
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.
Sorry, I jumped the gun with this request – I thought it would be difficult to solve but the jquery tabs docs (http://jqueryui.com/demos/tabs/#event-show) 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.
This is the code turned into a jQuery plugin: http://jsfiddle.net/andrewtomici/4mW2S/
It’s easier to use it this way.
Save the JavaScript code from the jsfiddle in a js file.
Example code:
$(‘.comments’).autoresize();
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 ?
thanks.
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.
Sure no problem. http://jsfiddle.net/KrvnK/1/
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.
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 screenr.com, showing what is happening in IE8 compared to IE7? That would be helpful, so I can see what you’re talking about. Thanks.
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.
Yes and I bet in some cases even possibly set the height of it via php. Thank you for the solution!
Why you don`t use
$(...).bind('input propertychange', ...)?
It works great for me!
Yep, that seems to work too. Also,
.on()(instead of.bind()) is the preferred method for attaching event handlers as described here.too complicated.
$(‘.editnote’).live(‘keyup’, function(e) {
var height = $(this).height();
var scrollheight = $(this).scrollTop();
if((scrollheight + height) > height) {
$(this).height(height + 16 + ‘px’);
}
});
Nice… except you shouldn’t use “live”, use “on” instead, and your version doesn’t resize the height when you remove text:
http://jsbin.com/afotuh/1/edit
But that could probably be easily added. Personally, I like the scrollHeight solution discussed here.
Thanks you!!
thanks, been looking for this :D
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!
Made it work on all textareas that have .auto-resize on them.
http://jsfiddle.net/fGNNT/1789/