Auto Grow a Textarea with Javascript

Understanding scrollHeight Property

The key to understanding an auto-growing or self-resizing textarea is to understand the concept of scrollHeight.

Every HTML element has the scrollHeight property that gives the total height of its content. Total height of the content includes the height of the visible content, height of the hidden content (hidden due to the vertical scrollbar) and the top & bottom padding.

So scrollHeight = ENTIRE content & padding

You can get scrollHeight through Javascript :

document.querySelector("#textarea-element").scrollHeight

Or with jquery :

$("#textarea-element").get(0).scrollHeight

Understanding how Auto-Growing a Textarea Works

In normal cases when content in a textarea overflows, you get to see the scrollbar. Now to make the textarea autogrow, you must hide the scrollbar and adjust the height of the textarea to the height of the contents in it. This adjustment of height should occur whenever the height of the contents change.

scrollHeight of the textarea will give you the height of the entire content of the textarea. With each keydown event (or keyup or input), you must make the height of the element equal to its scrollHeight.

Demo

Try entering text in the below textarea, and see it auto-grow :

HTML / CSS / Javascript

<textarea id="message-box"></textarea>
#message-box {
	resize: none;
	width: 400px;
	min-height: 100px;
	padding: 5px;
	overflow: hidden;
	box-sizing: border-box;
}

Javascript / jQuery :

$("#message-box").on('keydown', function() {
	var scroll_height = $("#message-box").get(0).scrollHeight;

	$("#message-box").css('height', scroll_height + 'px');
});

Make sure that you are setting box-sizing: border-box. Otherwise you will see that textarea grows in size with each keydown event. This happens because when you set CSS height to scrollHeight, height = scrollheight + top & bottom padding. Now updating the height will update the scrollHeight as well, and on the next occurance of the event, padding is added again. This almost becomes a loop with padding being added every time. You can find more in this Stack Overflow question.

Understanding clientHeight, offsetHeight & scrollHeight