How is textarea's scrollHeight and clientHeight calculated?
When you run this snippet you will see the following (at least in Chrome 97.0.4692.71):
- On page load,
clientHeight
andscrollHeight
are more than is necessary for 1 line. -
line-height
isundefined
unless explicitly set. Settingline-height
affects the initialclientHeight
andscrollHeight
values. - Entering 1 line break doesn't change
clientHeight
orscrollHeight
. They appear to initialize with enough room for 2 lines. - Entering 2 line breaks increases
scrollHeight
, as expected, but it doesn't equaltextHeight
. - Entering enough characters to wrap causes
scrollHeight
to increase but there are no line breaks added to the text (i.e.textHeight
doesn't change).
What are the calculations used to arrive at the clientHeight
and scrollHeight
values observed?
const textarea = document.querySelector('textarea');
document.addEventListener('DOMContentLoaded', () => {
resize(textarea);
});
textarea.addEventListener('input', (inputEvent) => {
resize(inputEvent.target);
});
function resize(o) {
const lines = getLines(o);
const fontSize = getCSSIntegerValue(o, 'font-size');
const padding = getCSSIntegerValue(o, 'padding');
const borderWidth = getCSSIntegerValue(o, 'border-width');
const textHeight = fontSize * lines;
console.log('fontSize=%d, lines=%d, padding=%d, borderWidth=%d, textHeight=%d, clientHeight=%d, scrollHeight=%d', fontSize, lines, padding, borderWidth, textHeight, o.clientHeight, o.scrollHeight);
}
function getCSSIntegerValue(o, property) {
const computedValues = window.getComputedStyle(o);
const propertyValue = computedValues.getPropertyValue(property);
return parseInt(propertyValue.replace(/\D/g, ''));
}
function getLines(o) {
const lines = o.value.split(/\r|\r\n|\n/);
return lines.length;
}
textarea {
all: unset;
background-color: #ddd;
overflow-y: hidden;
overflow-x: hidden;
overflow-wrap: break-word;
font-size: medium;
}
<textarea></textarea>
line-height
, unless defined, is going to use the user agent stylesheet (typically 1.2 for desktop browsers, according to MDN.) With that information, the results should make more sense.
clientHeight
is always 2 * line-height
.
scrollHeight
is line-height * lines
.