Textarea Auto height [duplicate]
Asked Answered
C

8

253

I want to make height of textarea equal to height of the text within it (And remove the scroll bar)

HTML

<textarea id="note">SOME TEXT</textarea>

CSS

textarea#note {
    width:100%;
    direction:rtl;
    display:block;
    max-width:100%;
    line-height:1.5;
    padding:15px 15px 30px;
    border-radius:3px;
    border:1px solid #F7E98D;
    font:13px Tahoma, cursive;
    transition:box-shadow 0.5s ease;
    box-shadow:0 4px 6px rgba(0,0,0,0.1);
    font-smoothing:subpixel-antialiased;
    background:linear-gradient(#F9EFAF, #F7E98D);
    background:-o-linear-gradient(#F9EFAF, #F7E98D);
    background:-ms-linear-gradient(#F9EFAF, #F7E98D);
    background:-moz-linear-gradient(#F9EFAF, #F7E98D);
    background:-webkit-linear-gradient(#F9EFAF, #F7E98D);
}

JsFiddle: http://jsfiddle.net/Tw9Rj/

Cosenza answered 21/7, 2013 at 12:19 Comment(3)
exampleFloc
Just at page load, or dynamically as user edits the content?Driskell
more suitable solution is to use contenteditable tag which has the default behavior. w3schools.com/tags/…Merideth
C
65

It can be achieved using JS. Here is a 'one-line' solution using elastic.js:

$('#note').elastic();

Updated: Seems like elastic.js is not there anymore, but if you are looking for an external library, I can recommend autosize.js by Jack Moore. This is the working example:

autosize(document.getElementById("note"));
textarea#note {
	width:100%;
	box-sizing:border-box;
	direction:rtl;
	display:block;
	max-width:100%;
	line-height:1.5;
	padding:15px 15px 30px;
	border-radius:3px;
	border:1px solid #F7E98D;
	font:13px Tahoma, cursive;
	transition:box-shadow 0.5s ease;
	box-shadow:0 4px 6px rgba(0,0,0,0.1);
	font-smoothing:subpixel-antialiased;
	background:linear-gradient(#F9EFAF, #F7E98D);
	background:-o-linear-gradient(#F9EFAF, #F7E98D);
	background:-ms-linear-gradient(#F9EFAF, #F7E98D);
	background:-moz-linear-gradient(#F9EFAF, #F7E98D);
	background:-webkit-linear-gradient(#F9EFAF, #F7E98D);
}
<script src="https://rawgit.com/jackmoore/autosize/master/dist/autosize.min.js"></script>
<textarea id="note">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</textarea>

Check this similar topics too:

Autosizing textarea using Prototype

Textarea to resize based on content length

Creating a textarea with auto-resize

Clausewitz answered 21/7, 2013 at 12:25 Comment(10)
I want to do it with css.Cosenza
I'm not sure it's possible with CSS.Clausewitz
gave this a shot since it was the accepted answer but when i started typing in my textarea it froze my browser for a few seconds then spit out everything i had typed at once. ended up rolling my own based on @brettof86 answer.Pigment
For future peeps: I think brettof86 changed their username to blockloop, so the answer being referred to is the angular one below:Piderit
elasticjs is a nice thing, I just added a class 'elastic' to the textareas of my target and then $('textarea.elastic').elastic()Argilliferous
elastic js demo doesn't work for me: firefox 47, chrome 51.Graves
The link of elastic js is broken...Negligee
Instead of referring to just a library, a better answer would have been one without the requirement of any external libraries. This answer probably hasn't helped anyone in some time.Fleenor
@JayantBhawal I agree. It's a disgrace that an answer on this site can be "use a third party library". That's not an answer, a cursory google search could have told me that. I don't want a third party library.Goodness
Thank you for criticizing me guys, but the decision to accept it as the answer wasn't mine, and I won't mind if it's going to be someone's else approach accepted. I just did my best and suggested a ready-to-use solution. Since it's not possible to achieve this via CSS, at the end of the day you will end up using JS most likely, so why not to consider to use the one that already has been written. And yes, you can google for it, but I did this job for you.Clausewitz
S
567

This using Pure JavaScript Code.

function auto_grow(element) {
  element.style.height = "5px";
  element.style.height = (element.scrollHeight) + "px";
}
textarea {
  resize: none;
  overflow: hidden;
  min-height: 50px;
  max-height: 100px;
}
<textarea oninput="auto_grow(this)"></textarea>
Sackville answered 10/7, 2014 at 12:23 Comment(17)
If you add some additional height it will stop the text from scrolling for the split second before the element is resized. (element.scrollHeight+20)+"px";Raylenerayless
works nice but has initial "jump". adding: if (element.scrollHeight > 80) { element.style.height = 5 + "px"; element.style.height = (element.scrollHeight + 10) + "px"; } helped. (min-height: 80px)Shoreward
may I suggest to use oninput? and height = auto instead of 5px?Polyhydric
FWIW I tried height=auto in a control and found that the textarea wouldn't shrink back to 1 line (in Chrome) - the smallest it would go is 2 lines, even if there was one line (or no) text. height=5px is making the textarea shrink correctly in my implementation.Lemus
@StefanMohr To fix this, set the textarea's rows attribute to 1.Telegony
Simple Inline JS solution <textarea class="form-control" onkeyup="$(this).height(5);$(this).height($(this).prop('scrollHeight'))"></textarea>Thermoelectrometer
I found useful to call auto_grow() on keydown using setImmediate(auto_grow, my_elem) to avoid delay.Rexferd
Doesn't work when text is modified (selected, cut, or pasted) using the mouse or right click menu. Use the input event instead of keyup event.Goeselt
If the height is 5px, even very briefly, the bottom of the webpage comes up and moves the viewport, then it moves again when the height is corrected. Try putting lots of content into that textarea and typing new lines into it to see what I mean.Standridge
Does not work if text overflows horizontallyGlycerinate
It appears that having the event fired also onkeydown can covers the scenario when users hold the delete key to delete content (or less likely, holding a normal key to type the same character)Giotto
I think correct calculating of optimal textarea height is var scrollHeight = Math.max(this.scrollHeight, this.offsetHeight, this.clientHeight) Because calculating these params in Chrome/Safari and Opera different. So safety way is take Max of them )Fortuitous
Guys I implemented this code and it works great especially after changing the event to input since the user may copy paste text as well. But on emptying the div after submit, the div doesn't come back to its original size. I have posted my question here. Please take a look #61633085Finsen
Temporarily set the minHeight of the parent to prevent the page jumping around: element.parentNode.style.minHeight = element.parentNode.clientHeight + "px"; element.style.height = "5px"; element.style.height = (element.scrollHeight)+"px"; element.parentNode.style.minHeight = 0;Birkenhead
This solution worked for me if I set style="resize: none; overflow: hidden; height: 100%;"Shifra
This has a bug. When deleting content from the textarea, the height does not shrink.Phlebotomize
@Nicholas. An additional advantage for the user of adding a bottom blank area of at least a line height in a textarea is that it indicates that more content can be added, whereas making the control just fit the existing text doesn't. That it continues to expand with the extra space as more text is added further reinforces thisLobelia
S
119

For those of us accomplishing this with Angular JS, I used a directive

HTML:

<textarea elastic ng-model="someProperty"></textarea>

JS:

.directive('elastic', [
    '$timeout',
    function($timeout) {
        return {
            restrict: 'A',
            link: function($scope, element) {
                $scope.initialHeight = $scope.initialHeight || element[0].style.height;
                var resize = function() {
                    element[0].style.height = $scope.initialHeight;
                    element[0].style.height = "" + element[0].scrollHeight + "px";
                };
                element.on("input change", resize);
                $timeout(resize, 0);
            }
        };
    }
]);

$timeout queues an event that will fire after the DOM loads, which is what's necessary to get the right scrollHeight (otherwise you'll get undefined)

Sulfathiazole answered 6/6, 2014 at 21:16 Comment(13)
Sweet, thanks for posting! Just wanted to add that I was having an issue where removing lines of text wouldn't decrease the height enough (2px at a time, possibly related to using bootstrap). I fixed this by setting element[0].style.height in the resize function to 1px first, then setting it to the scrollHeight.Toponym
It didn't shrink for me. I added a couple lines so it shrinks until its default/initial height. link: function($scope, element) { $scope.initialHeight = $scope.initialHeight || element[0].style.height; var resize = function() { element[0].style.height = $scope.initialHeight; element[0].style.height = "" + element[0].scrollHeight + "px"; }; element.on("blur keyup change", resize); $timeout(resize, 0); }Willms
This is great. I also needed resize when the model changes (my comments box is dynamic). So I added: $scope.$watch(attrs.ngModel, resize);Delbert
@Bob element.on("blur keyup change", resize) should cover model changes.Sulfathiazole
It's better to use element.on('input change') - otherwise resize is only called after a render and it will flicker.Bullnose
Good call @Bullnose I'll update the answerSulfathiazole
Excellent solution @SulfathiazoleMalvaceous
It's quite old, but I'll give it a try. I'm using this but the scrollHeight is always 0 while the value of the textarea is set when i look at it during debugging. Any ideas?Prichard
Experiencing the same thing as @Prichard -- scrollHeight is 0. Seems this is happening when it's contained within an ancestor element that is shown/hidden via ngShow.Heteroplasty
Thanks for the angular directive approach. This got me pointed to using the ng-elastic package on npm for Angular 2+: npmjs.com/package/ng-elasticNellynelms
if(element[0].scrollHeight > 0) element[0].style.height = "" + element[0].scrollHeight + "px";Largeminded
@NuriHodges @Prichard you can use this $watch here to fix the scroll height 0 problem for display:none elements. #19049485Sugarplum
Does anyone have AngularX solution?Discretional
C
65

It can be achieved using JS. Here is a 'one-line' solution using elastic.js:

$('#note').elastic();

Updated: Seems like elastic.js is not there anymore, but if you are looking for an external library, I can recommend autosize.js by Jack Moore. This is the working example:

autosize(document.getElementById("note"));
textarea#note {
	width:100%;
	box-sizing:border-box;
	direction:rtl;
	display:block;
	max-width:100%;
	line-height:1.5;
	padding:15px 15px 30px;
	border-radius:3px;
	border:1px solid #F7E98D;
	font:13px Tahoma, cursive;
	transition:box-shadow 0.5s ease;
	box-shadow:0 4px 6px rgba(0,0,0,0.1);
	font-smoothing:subpixel-antialiased;
	background:linear-gradient(#F9EFAF, #F7E98D);
	background:-o-linear-gradient(#F9EFAF, #F7E98D);
	background:-ms-linear-gradient(#F9EFAF, #F7E98D);
	background:-moz-linear-gradient(#F9EFAF, #F7E98D);
	background:-webkit-linear-gradient(#F9EFAF, #F7E98D);
}
<script src="https://rawgit.com/jackmoore/autosize/master/dist/autosize.min.js"></script>
<textarea id="note">Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.</textarea>

Check this similar topics too:

Autosizing textarea using Prototype

Textarea to resize based on content length

Creating a textarea with auto-resize

Clausewitz answered 21/7, 2013 at 12:25 Comment(10)
I want to do it with css.Cosenza
I'm not sure it's possible with CSS.Clausewitz
gave this a shot since it was the accepted answer but when i started typing in my textarea it froze my browser for a few seconds then spit out everything i had typed at once. ended up rolling my own based on @brettof86 answer.Pigment
For future peeps: I think brettof86 changed their username to blockloop, so the answer being referred to is the angular one below:Piderit
elasticjs is a nice thing, I just added a class 'elastic' to the textareas of my target and then $('textarea.elastic').elastic()Argilliferous
elastic js demo doesn't work for me: firefox 47, chrome 51.Graves
The link of elastic js is broken...Negligee
Instead of referring to just a library, a better answer would have been one without the requirement of any external libraries. This answer probably hasn't helped anyone in some time.Fleenor
@JayantBhawal I agree. It's a disgrace that an answer on this site can be "use a third party library". That's not an answer, a cursory google search could have told me that. I don't want a third party library.Goodness
Thank you for criticizing me guys, but the decision to accept it as the answer wasn't mine, and I won't mind if it's going to be someone's else approach accepted. I just did my best and suggested a ready-to-use solution. Since it's not possible to achieve this via CSS, at the end of the day you will end up using JS most likely, so why not to consider to use the one that already has been written. And yes, you can google for it, but I did this job for you.Clausewitz
A
15

I used jQuery AutoSize. When I tried using Elastic it frequently gave me bogus heights (really tall textarea's). jQuery AutoSize has worked well and hasn't had this issue.

Agaric answered 9/4, 2014 at 21:6 Comment(0)
C
13

I see that this is answered already, but I believe I have a simple jQuery solution ( jQuery is not even really needed; I just enjoy using it ):

I suggest counting the line breaks in the textarea text and setting the rows attribute of the textarea accordingly.

var text = jQuery('#your_textarea').val(),
    // look for any "\n" occurences
    matches = text.match(/\n/g),
    breaks = matches ? matches.length : 2;

jQuery('#your_textarea').attr('rows',breaks + 2);
Counterpoint answered 18/10, 2013 at 3:56 Comment(3)
That's pretty slick. This seems to work nicely: textarea.on('input propertychange keyup change', function(){ this.rows = this.value.match(/\n/g).length + 1 })Duong
Good solution. Note that it doesn't apply to those who use display:block.Strap
Except it doesn't work if the text wraps. If the text wraps, the number of lines of text is not equivalent to the number of newline characters, since wrapping causes lines to break at white space between words.Lollipop
L
7

Jsfiddle

textarea#note {
    width:100%;
    direction:rtl;
    display:block;
    max-width:100%;
    line-height:1.5;
    padding:15px 15px 30px;
    border-radius:3px;
    border:1px solid #F7E98D;
    font:13px Tahoma, cursive;
    transition:box-shadow 0.5s ease;
    box-shadow:0 4px 6px rgba(0,0,0,0.1);
    font-smoothing:subpixel-antialiased;
    background:-o-linear-gradient(#F9EFAF, #F7E98D);
    background:-ms-linear-gradient(#F9EFAF, #F7E98D);
    background:-moz-linear-gradient(#F9EFAF, #F7E98D);
    background:-webkit-linear-gradient(#F9EFAF, #F7E98D);
    background:linear-gradient(#F9EFAF, #F7E98D);
    height:100%;
}
html{
    height:100%;
}
body{

   height:100%;    
}

or javascript

var s_height = document.getElementById('note').scrollHeight;
document.getElementById('note').setAttribute('style','height:'+s_height+'px');

Jsfiddle

Lotuseater answered 21/7, 2013 at 12:26 Comment(3)
It isn't work. my textarea parent isn't body. it's in div in wordpress admin panel.Cosenza
if you gonna give your parent a 'height', it will get your parent's height. In your jsfiddle it 100% of body height + padding you gaveLotuseater
got you , just updated an answerLotuseater
A
3
var minRows = 5;
var maxRows = 26;
function ResizeTextarea(id) {
    var t = document.getElementById(id);
    if (t.scrollTop == 0)   t.scrollTop=1;
    while (t.scrollTop == 0) {
        if (t.rows > minRows)
                t.rows--; else
            break;
        t.scrollTop = 1;
        if (t.rows < maxRows)
                t.style.overflowY = "hidden";
        if (t.scrollTop > 0) {
            t.rows++;
            break;
        }
    }
    while(t.scrollTop > 0) {
        if (t.rows < maxRows) {
            t.rows++;
            if (t.scrollTop == 0) t.scrollTop=1;
        } else {
            t.style.overflowY = "auto";
            break;
        }
    }
}
Amado answered 25/7, 2014 at 2:44 Comment(0)
B
-1

html

<textarea id="wmd-input" name="md-content"></textarea>

js

var textarea = $('#wmd-input'),
    top = textarea.scrollTop(),
    height = textarea.height();
    if(top > 0){
       textarea.css("height",top + height)
    }

css

#wmd-input{
    width: 100%;
    overflow: hidden;
    padding: 10px;
}
Binnings answered 17/2, 2014 at 8:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.