Delete your auto-resize textarea script
Set markodenic.tech as your preferred Google source
Creem.io
Merchant of record payments for SaaS and digital products, handling checkout, subscriptions, taxes, invoices, and global payment operations.
Every project ends up with the same 10 lines: listen for input, set height to auto, read scrollHeight, set height to that. It works until the textarea starts hidden, or the font loads late, or you forget to call it once on page load with the saved draft already in there.
The browser does this natively now. One CSS property, and the listener goes away.
The fix
textarea {
field-sizing: content;
min-height: 3lh;
max-height: 12lh;
}
That’s the whole feature. The textarea starts 3 lines tall, grows as the user types, and stops at 12 lines and starts scrolling instead.
field-sizing: content tells the element to size itself to its value instead of to the rows attribute. lh is one line height of the element’s own font, so the limits stay correct when the font size changes.
Type in this box and watch it grow. There is no JavaScript on that page.
Grows from 3 lines to 12, then scrolls. No JavaScript on this page.
This browser does not support field-sizing yet, so the textarea stays at
its rows="3" size. Nothing else changes.
Where this comes up
- Comment and reply boxes: the classic case, and the one people install a package for.
- Chat inputs: a single line that expands as someone writes a paragraph.
- Admin forms: description fields where every record has a wildly different length.
- Anything with a saved draft: if you’re restoring the value from localStorage, the JS version needs a manual resize call right after. This one just renders correctly.
The details that matter
Set both limits. With field-sizing: content and no min-height, an empty textarea collapses to a single line, which is a small target and looks broken. A placeholder changes that: the browser sizes the empty field to fit the placeholder text, so the box you get depends on how long that string is. min-height makes it predictable either way. Without max-height, one pasted essay pushes your submit button off the screen.
Constrain the width. A textarea with field-sizing: content grows sideways first, and only starts adding lines once its width is capped. width: 100%, a max-width, or any explicit width gets you the vertical-only growth people picture when they hear “auto-resize”.
rows stops controlling the size. It still belongs in the markup as the fallback for browsers that don’t support the property yet, but min-height is what wins where the property works.
Manual resizing still applies. Users can drag the corner, and the moment they do, their height wins. If you want the browser fully in charge:
textarea {
field-sizing: content;
resize: none;
}
It works on inputs too. An <input> with field-sizing: content shrinks to fit its value, which is what you want for inline “click to edit” fields:
.inline-edit {
field-sizing: content;
min-width: 6ch;
}
Give it a min-width or an empty field becomes a few pixels wide. The same property covers the text-like input types: search, email, url, tel, password, number. And <select>, where the box shrinks to fit whichever option is selected.
Browser support
All three engines ship it now. Firefox 152 landed in June 2026, which is the release that made field-sizing Baseline. Chrome and Edge have had it since 123 in March 2024, Safari since 26.2.
Baseline describes the latest versions, not the ones people are actually running. Global support sits around 84%, so roughly one in six visits still comes from a browser that ignores the property. There the textarea stays the size rows gives it, which is exactly what your textareas do today. Nothing breaks, nobody sees an error.
If a specific form really needs the behavior everywhere, keep the script and load it only where the native version is missing:
if (!CSS.supports('field-sizing', 'content')) {
// your existing autoGrow() here
}
Why this matters
- The bug you’ve already shipped: a textarea rendered with a saved draft in it, sized like it’s empty. There’s no init call to forget here, because there’s no init.
- Nothing runs while typing: reading
scrollHeightforces the browser to lay the page out, and the script version does that on every character. - It survives the font loading late: the browser resizes when the font swaps in. Your listener only runs when someone types.
Search your codebase for scrollHeight. Every hit inside a textarea handler is a block of code you can delete this afternoon. While you’re in there, the popover attribute retires the tooltip and dropdown scripts sitting next to it.
Happy coding!
Marko