Drop a plain <textarea> into a form where everything else is set in Inter at 16px, and it will show up in Courier at roughly 13px. It’ll have a little drag handle in the corner that lets anyone pull it wider than your layout, and it’ll sit at two rows tall no matter how much someone types into it. None of that is a bug in your code. Those are the browser’s own defaults for the element, and they’ve been around since long before most design systems existed.
All three problems can be fixed with a few lines of CSS. The font fix and the resize fix work in every browser today, and the auto-height fix now works in every major browser engine too, though older versions of Safari and Firefox still need a fallback.
Why The Textarea Doesn’t Use Your Page Font
Form controls don’t inherit font styles the way a paragraph or a div does. Chrome and Firefox both give <textarea> a monospace font in their built-in stylesheets, and every browser sets its own smaller font size on it as well. So your body { font-family: ... } rule never reaches it.
The Font Fix
Tell the textarea to take its font from the parent element:
textarea {
font-family: inherit;
font-size: inherit;
line-height: 1.5;
}
Setting a line-height here matters more than it looks. The height fix further down uses the lh unit, which is based on this value, so a predictable line height now saves a lot of guessing later.
If you’d rather not list each property, font: inherit; covers the family, size, weight and style in one line. You may also want color: inherit;, since some browsers set their own text color on form fields too.
Why Font Size Matters On iPhones
There’s one more reason to make sure the font size inherits properly. On iOS Safari, if a textarea’s font size is smaller than 16px, the page zooms in when someone taps into it, and it doesn’t always zoom back out. Leaving the browser’s default size in place is one of the most common causes of that annoying jump on mobile forms. If your body text is 16px or larger, inheriting it solves the problem.
How To Stop Users Resizing The Textarea
The handle in the bottom right corner comes from the resize property, which browsers set to both on text areas by default. That lets someone drag the box wider than its column and push the rest of the layout around.
The resize property gives you four choices:
noneremoves the handle completely.verticallets people make it taller or shorter but keeps the width fixed.horizontalallows width changes only, which is rarely what anyone wants.bothis the default.
/* No manual resizing at all */
textarea.no-resize {
resize: none;
}
/* Taller or shorter only, width stays locked */
textarea.vertical-only {
resize: vertical;
}
For most forms, vertical is a sensible middle ground. People writing a long message can still give themselves more room, and the layout stays intact.
How To Make A Textarea Grow As People Type
For years, the only way to get a text area to expand with its content was JavaScript. A script would listen for every keystroke, read the element’s scrollHeight and set the height to match. It worked, but it could lag, and it was one more thing to maintain.
CSS now has a property that does this on its own. field-sizing: content tells the browser to size the field around whatever is inside it, rather than around the rows attribute.
textarea.auto-grow {
field-sizing: content;
min-height: 2lh;
max-height: 6lh;
box-sizing: border-box;
}
The lh unit equals one line of text at the element’s current line height. So 2lh means two lines tall and 6lh means six. Once the text goes past six lines, the text area stops growing and shows a scrollbar instead. The nice part is that if you change the font size or line height later, those limits adjust along with it.
Why Min-Height Cuts Off Text With Border-Box
The snippet above has one issue to fix before you copy it into a project. With box-sizing: border-box, the min-height includes the padding and the border. Give the textarea 0.5rem of padding, and 2lh will no longer fit two full lines of text. The second line gets squeezed.
There are two simple ways around it:
- Add the padding and border into the calculation, for example
min-height: calc(2lh + 1rem + 2px);when you have0.5rempadding top and bottom and a 1px border. - Leave the textarea on
box-sizing: content-box, somin-heightandmax-heightonly measure the text area itself.
Things That Change Once Field-Sizing Is On
The rows and cols attributes stop controlling the size once field-sizing: content is applied. An empty textarea will shrink down to fit its placeholder text, or to almost nothing if there isn’t one. That’s why the min-height line isn’t optional. Without it, the field can end up looking like a single-line input.
Placeholder text also counts as content for sizing. A long placeholder will make an empty textarea taller than you might expect.
Which Browsers Support Field-Sizing
Chrome and Edge added field-sizing in version 123, back in 2024. Safari followed in 26.2, and Firefox shipped it in version 152 in June 2026, which made it available across all the major browser engines. Can I Use puts global support at around 87% of users.
That leaves a slice of visitors on older Safari and Firefox builds who won’t get the auto-grow. Nothing breaks for them. The textarea falls back to its normal fixed height and scrolls. If you’d like those users to get a reasonable starting size, keep a rows attribute in the HTML and wrap the auto-grow rules in a feature check:
@supports (field-sizing: content) {
textarea {
field-sizing: content;
min-height: 3lh;
max-height: 10lh;
}
}
Browsers that understand field-sizing will grow the field. The rest will use the rows value as before.
Should Resize And Auto-Grow Be Used Together?
They can be, as long as you know what happens. When someone drags the resize handle, the browser sets a fixed height on the textarea. From that point on, it stops growing with the text, because that height now wins over field-sizing.
If the textarea grows on its own, most people won’t need the handle anyway. For auto-growing fields, resize: none is usually the cleaner choice. Keep resize: vertical on fields where you aren’t using field-sizing, so people still have a way to get more room.
A Textarea Baseline To Reuse On Every Form
This is everything above combined into one rule set that can sit in a base stylesheet:
textarea {
/* Font */
font: inherit;
color: inherit;
line-height: 1.5;
/* Box */
box-sizing: border-box;
width: 100%;
padding: 0.5rem;
/* Manual resizing for browsers without auto-grow */
resize: vertical;
}
@supports (field-sizing: content) {
textarea {
field-sizing: content;
/* 3 lines of text plus top and bottom padding and a 1px border */
min-height: calc(3lh + 1rem + 2px);
max-height: calc(10lh + 1rem + 2px);
resize: none;
}
}
With rows="3" in the HTML as well, older browsers get a three-line box that people can stretch downward, and newer ones get a field that starts at three lines and grows to ten. In both cases, the text will match the rest of the form.
