Why do we set textarea height to '0px' before setting it equal to its scrollHeight in order to auto size the textarea?
Asked Answered
S

1

2

I am using the code from https://mcmap.net/q/74850/-textarea-auto-height-duplicate and modifying it for my question (mainly replacing element.style.height = "5px" with element.style.height = "0px"). My question is why do we even need to reset the textarea height before setting its height with its scrollHeight ?

function auto_grow(element) {
    element.style.height = "0px"; // why do we even need this line ?
    element.style.height = (element.scrollHeight)+"px";
}
<textarea oninput="auto_grow(this)"></textarea>

It does give weird behavior with this line element.style.height = "0px" commented out as can be seen by running the code snippet below but what is causing this ? Does the scrollHeight attribute compute its value in a different way when the textarea height is not reset in the oninput handler ?

function auto_grow(element) {
    console.log(`Before- ${element.scrollHeight}`);
    // element.style.height = "0px";
    element.style.height = (element.scrollHeight)+"px";
    console.log(`After- ${element.scrollHeight}`);
}
<textarea
  oninput="auto_grow(this)"></textarea>
Schelling answered 30/8, 2021 at 11:42 Comment(1)
If you add console.log(element.scrollHeight) right before and after updating the element height maybe you can have a better understanding of what's going on.Martie
P
1

There's a couple of things going on. The textarea starts with an initial content height, a padding of 2px (on all sides, but specifically for this case, top and bottom) and a box-sizing of content-box.

The next thing to understand is how the scrollheight of an element is calculated. It's from the top edge of the scrolling area to the bottom edge. The top edge is the top edge of its padding box. The bottom edge is defined as

The bottom-most edge of the element’s bottom padding edge and the bottom margin edge of all of the element’s descendants' boxes, excluding [not relevant in this case].

The text content generates descendant boxes, so this means that when you measure the scrollHeight of the textarea, that's the height of top padding plus the maximum of the existing set content height + bottom padding and the text height.

By setting the content height to 0px first, it's reducing that scrollHeight to the height of top padding plus the maximum of the bottom padding and the text height, which for all practical purposes is always going to be the height of the text.

So the final content height set will always be set to the height of the contained text plus the top padding.

Punctuate answered 30/8, 2021 at 18:32 Comment(1)
Amazing explanation, although i had to revisit your answer a few times to wrap my head around it. And combining it with @iamdlm's pointer about logging scrollHeight before and after, your answer perfecty explains what's going on.Schelling

© 2022 - 2024 — McMap. All rights reserved.