175

I need a textarea where I type my text in the box, it grows in length as needed to avoid having to deal with scroll bars and it need to shrink after delete text! I didn’t want to go down the mootools or jquery route because I have a lightweight form.

Alex Rozanski
  • 37,815
  • 10
  • 68
  • 69
Santanu
  • 7,764
  • 7
  • 26
  • 24

8 Answers8

307

You can check the content's height by setting to 1px and then reading the scrollHeight property:

function textAreaAdjust(element) {
  element.style.height = "1px";
  element.style.height = (25+element.scrollHeight)+"px";
}
<textarea onkeyup="textAreaAdjust(this)" style="overflow:hidden"></textarea>

It works under Firefox 3, IE 7, Safari, Opera and Chrome.

Andria
  • 4,712
  • 2
  • 22
  • 38
Alsciende
  • 26,583
  • 9
  • 51
  • 67
  • 1
    There's a problem in Firefox, if your user inputs a very long word (no white space, larger than the textarea) then "overflow:hidden" will prevent her from seeing the right end of the word. Other browsers don't care since they will line-break even without white spaces. You can remedy to this by using "overflow-y:hidden" instead, but then your css is not standards-compliant. – Alsciende Jun 15 '09 at 12:27
  • Regarding the Firefox problem, it might be resolved soon: http://stackoverflow.com/questions/47817/most-elegant-way-to-force-a-textarea-element-to-line-wrap-regardless-of-whites – Alsciende Jun 15 '09 at 12:33
  • 2
    If you textarea is too tall and generates scroll on the page **and** you happen to have your page scrolled down, this will reset the scroll position to the top when you 'height = 1px'. To avoid it you can assign the height to the textarea's parent temporarily. – Jens Jul 03 '12 at 01:56
  • https://developer.mozilla.org/en-US/docs/DOM/element.scrollHeight → "scrollHeight is part of the MSIE's DHTML object model. scrollHeight is not part of any W3C specification or technical recommendation." But it seems to work nevertheless: http://www.quirksmode.org/dom/w3c_cssom.html#t36 However, note that it doesn't decrease the textarea size after it has been increased. – Denilson Sá Maia Sep 20 '12 at 18:32
  • 13
    This is a very similar answer: http://stackoverflow.com/a/5346855/124946 If we set `height='auto'` right before setting it to `scrollHeight`, then it works as expected, shrinking as needed. – Denilson Sá Maia Sep 20 '12 at 19:04
  • This small piece of code is doing the trick :-) Really nice and fast when dealing with multiple textares in a page. – Hallgeir Engen Nov 09 '12 at 08:27
  • This is a much better solution (as far as being light-weight) than any I've seen, and I've been looking all over. Thank you! – levininja Feb 11 '14 at 21:49
  • 3
    This has a problem when the textarea gets taller than the view port. In that case when the textarea grows it gets jittery. Otherwise quite nice. – Quentin Engles May 01 '14 at 03:10
  • jQuery solution (based on this): `` `$(function() { $('textarea.autoheight').each(function() { $(this).height(1); $(this).height(10 + $(this).get(0).scrollHeight); }); });` – Terri Ann Dec 05 '14 at 04:16
  • This is a good solution, but in some cases you may see the height shrink and expand every time a line break happens. One approach to avoid this would be to clone the element off screen somewhere and determine the correct height on the clone. In this way, you'll only be setting the target element's height once per keystroke. – Aaron Cicali Sep 03 '15 at 17:35
  • it is not working for ie 10 – Elangovan Dec 26 '15 at 12:19
  • So if I right click from the mouse and paste, the resize does not happen. I guess we could also use the mouse down event and have a similar action for that. – AshD Oct 27 '17 at 06:03
  • for angular 2+, el.target.style.height and el.target.scrollHeight – Igor Beaufils Apr 20 '21 at 20:46
  • `You can check the content's height by setting to 1px and then reading the scrollHeight property` i find that part of the answer really intriguing, why scrollHeight does not give the correct content height without resetting the height first.. Added a separate question on that https://stackoverflow.com/questions/68983541/why-do-we-set-textarea-height-to-0px-before-setting-it-equal-to-its-scrollheig. – oomer Sep 01 '21 at 10:35
  • this is not a particularly react friendly solution as reacts own internal rendering process might override styles set in js – John Miller Jan 06 '23 at 22:05
73

You may also try contenteditable attribute onto a normal p or div. Not really a textarea but it will auto-resize without script.

.divtext {
    border: ridge 2px;
    padding: 5px;
    width: 20em;
    min-height: 5em;
    overflow: auto;
}
<div class="divtext" contentEditable>Hello World</div>
Julian Schmuckli
  • 3,681
  • 11
  • 37
  • 64
billyswong
  • 1,114
  • 7
  • 12
  • 20
    this will, however, add all HTML rubbish when pasting. – Ernests Karlsons Oct 05 '11 at 16:14
  • See this answer to strip HTML rubbish: http://stackoverflow.com/a/20384452/59087 – Dave Jarvis Dec 31 '13 at 21:27
  • 3
    This solution is great if textarea is readonly. (That case contentEditable can be omitted) I would also add `white-space: pre;` setting. –  Sep 23 '14 at 11:12
  • Great solution! One improvement to make it more act like a textarea: I would add a cursor on hover the div box `.divtext:hover { cursor:text; }`. In my case I also modified the `.divtext:focus` class to change background color when focusing the text box. – Michael Dec 18 '15 at 01:25
  • 1
    still works in '19 with angular 7 and ngx-highlight `
    `
    – pcnate Feb 04 '19 at 16:45
  • this solution breaks a11y, it should be avoided. Just use the normal textarea HTML tag – Yuriy Kravets Nov 21 '21 at 12:31
12

Use this function:

function adjustHeight(el){
    el.style.height = (el.scrollHeight > el.clientHeight) ? (el.scrollHeight)+"px" : "60px";
}

Use this html:

<textarea onkeyup="adjustHeight(this)"></textarea>

And finally use this css:

textarea {
min-height: 60px;
overflow-y: auto;
word-wrap:break-word
}

The solution simply is letting the scrollbar appears to detect that height needs to be adjusted, and whenever the scrollbar appears in your text area, it adjusts the height just as much as to hide the scrollbar again.

Hazem_M
  • 549
  • 5
  • 11
  • i know that this is an old post but when I print the textarea, if the whole content does not fit in the first page, the whole contecnt goes to the second page and creates unwanted spaces on the first page. How can I split the textarea in two pages in printing? – Dale Jan 08 '16 at 03:37
  • For anyone with Dale's issue, there is css: `page-break-before:avoid` – AnorZaken Mar 04 '22 at 08:26
  • @AnorZaken The newer property is `break-before` but that aside, it's not quite browser compatible. Support for some values is even missing in FF. – aderchox Jul 28 '22 at 07:56
  • @aderchox Good point, and support is why it's still a good idea to continue using `page-break-before` - it has support from the stone age, and newer browsers treat it as an alias for `break-before`. However `avoid` is not supported on old FF unfortunately. – AnorZaken Aug 02 '22 at 13:55
11

A jquery solution has been implemented, and source code is available in github at: https://github.com/jackmoore/autosize .

Ravimallya
  • 6,550
  • 2
  • 41
  • 75
6

Alciende's answer didn't quite work for me in Safari for whatever reason just now, but did after a minor modification:

function textAreaAdjust(o) {
    o.style.height = "1px";
    setTimeout(function() {
        o.style.height = (o.scrollHeight)+"px";
    }, 1);
}

Hope this helps someone

davesmiths
  • 201
  • 2
  • 3
  • 1
    Sure that's a great solution... if you want to strobe your textarea every time the user presses a key. :V – Ethan May 17 '17 at 01:58
  • This worked to solve my problem at the time. Today, I would probably use jackmoore's jQuery solution given in Ravimallya's answer – davesmiths May 17 '17 at 11:30
0

Decide a width and check how many characters one line could hold, and then for each key pressed you call a function that looks something like:

function changeHeight()
{
var chars_per_row = 100;
var pixles_per_row = 16;
this.style.height = Math.round((this.value.length / chars_per_row) * pixles_per_row) + 'px';
}

Havn't tested the code.

Ivar
  • 4,344
  • 6
  • 38
  • 53
0

I don't think there's any way to get width of texts in variable-width fonts, especially in javascript.

The only way I can think is to make a hidden element that has variable width set by css, put text in its innerHTML, and get the width of that element. So you may be able to apply this method to cope with textarea auto-sizing problem.

Achimnol
  • 1,551
  • 3
  • 19
  • 31
0

You can achieve this by using a span and a textarea.

You have to update the span with the text in textarea each time the text is changed. Then set the css width and height of the textarea to the span's clientWidth and clientHeight property.

Eg:

.textArea {
    border: #a9a9a9 1px solid;
    overflow: hidden;
    width:  expression( document.getElementById("spnHidden").clientWidth );
    height: expression( document.getElementById("spnHidden").clientHeight );
}
Andrei
  • 10,918
  • 12
  • 76
  • 110
rahul
  • 184,426
  • 49
  • 232
  • 263