Delete Your Auto-Resize Textarea JS. CSS Does It Now.
The scrollHeight hack everyone copy-pastes for auto-growing textareas has a one-line CSS replacement — plus the one gotcha that bites if you skip max-height.

Open any comment box you've built in the last five years and there's a decent chance this is sitting in a useEffect or an input listener:
Two lines. Copy-pasted from a Stack Overflow answer, a gist, or your own last project. It's the unofficial industry-standard way to make a <textarea> grow as someone types, because <textarea> has never — not once, in thirty years of HTML — known how to size itself to its own content. Until now it does, and most people haven't heard.
Here's the fuller version most people actually ship, because the two-liner alone doesn't hold up:
Reset the height to auto, read scrollHeight, write it back. Do that on every keystroke. It works, but notice what "works" is quietly costing you:
- Two forced reflows per keystroke. Setting
height: autoinvalidates layout; readingscrollHeightforces the browser to recompute it synchronously before it'll give you the number. On a slow device, in a form with several of these, that's measurable jank while someone's just trying to type. - A visible flicker. Reset-then-remeasure means the box visibly shrinks for one frame before snapping back, especially noticeable on a fast paste of several paragraphs.
- You have to remember the resize listener. Miss it, and resizing the browser window leaves stale heights until the next keystroke — a bug that never shows up in your testing because you never resize your own window mid-demo.
- It still doesn't handle a
<input type="text">growing with its content, which is the same underlying problem in a different tag. You'd write a second version of this hack.
None of this is a bug in your code. It's the ceiling of what's possible when the browser gives you no way to say "size to content" and JavaScript has to fake it by measuring pixels after the fact.
That's the whole thing. No listener, no scrollHeight, no reflow-and-flicker dance. field-sizing is a CSS property that changes how form controls compute their intrinsic size: instead of the browser guessing a fixed box from rows/cols (or a fixed width for <input>), content tells it to size the box to fit what's actually typed, and grow or shrink live as the user edits.
It isn't limited to <textarea>. Point it at a text <input> and the field widens as someone types, the same trick people currently fake with a hidden <span> measuring text width behind the scenes:
As of mid-2026 this is Baseline "Newly available" — it started in Chromium browsers in 2024 and has since landed in the current stable release of every core engine, Firefox and Safari included. "Newly available" is the first rung on Baseline's ladder, though, not the last: it means the latest stable version of each browser understands it, not that every visitor is already on that version. If you need to support someone on an older browser, that's exactly what a plain, unstyled textarea already does — it just won't auto-grow, and nothing breaks. Ship it behind nothing and it degrades to the old fixed-size box on its own.
Here's the part that bites people who copy just the CSS and stop reading: field-sizing: content on its own means the box has no upper bound. Let someone paste in a full paragraph, or ten, and your neat little comment box grows into a page-length column, pushing your submit button somewhere past the fold.
You still need a ceiling — you just set it in CSS instead of computing it in JS:
max-height caps the growth, overflow-y: auto lets the box scroll internally once it hits that cap instead of just clipping the text. 12lh — twelve line-heights — is a nice unit to reach for here because it scales with the font size instead of hardcoding a pixel guess.
Try both settings live below: type a short reply, then paste in a wall of text, and watch where the ceiling kicks in. Then flip the toggle to see the exact JS hack this replaces, side by side.
Runs right in your browser — poke at it and watch the concept react live.
field-sizing: content replaces a hack that's been copy-pasted into countless codebases since <textarea> shipped without an opinion on its own size. It removes a resize listener, two forced reflows per keystroke, and a visible flicker on paste — for the cost of one CSS declaration and remembering to pair it with max-height.
If you're still shipping the scrollHeight version because "it works," it does — but so did jQuery .animate() before transition existed. Go check whether the browsers you actually support have caught up, and see how much JS you get to delete.
What's the oldest DOM-measuring hack you're still maintaining that you suspect CSS has quietly solved by now? Drop it below — I'll tell you if there's already a property for it.
Think it clicked? Take the 7-question quiz →
Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.
🚀 Want more like this? Every guide, playground, and quiz lives on bestpractic.org — open it and sign up free so the next one finds you.
Thanks for reading! Let's stay connected:
- ⭐ GitHub — follow me and star the projects: github.com/parsajiravand
- 💬 Discord — join the frontend best-practices community: discord.gg/d9KRhuAwQ
- 📸 Instagram — frontend best practices, daily: @bestpractice___
Keep reading
One post a day, in your inbox
Each one with a runnable playground and a quiz. No pitch, no digest, unsubscribe in one click.
0 comments
Sign in to join the discussion, like comments, and save articles for later.