Textarea
A textarea is a multi-line input for text that runs longer than one line: a comment, an address, a bug report. Its visible height is a promise about how much you expect someone to write.
<textarea>Also called Multi-line input, Text area, Comment box.
Give someone a single-line box and they write a single line, whatever the actual answer needs. Give them five visible rows and they write closer to five. A textarea's height works as an instruction: it tells the person filling it in roughly how much you expect, before they have written a word.
Anatomy of a textarea

- 1Label. Above the box, connected with for and id, same as a text field.
- 2Box. Starts at a height that matches the expected answer, not the smallest space that fits the label.
- 3Typed text. 16px minimum, same reason as a text field: Safari on iOS zooms the page in below that size.
- 4Border. 3:1 contrast against the page at rest (WCAG 1.4.11), with a focus ring that never disappears without a replacement.
- 5Resize handle. Native and mouse-only. Leave it on unless the box already autosizes to the content.
- 6Character count. Only where a real limit exists, shown as a number under the box and linked with
aria-describedby.
The parts below are mostly a text field's, plus one it does not have: a way to see more of a long answer, either by growing or by letting someone drag the corner themselves.
Here it is working. Type past the visible rows and watch what happens to the box rather than the scrollbar.
Type past the fifth line and the box grows to meet it, using field-sizing: content rather than a resize listener.
When to use a textarea
Use a textarea when
- The answer could run to more than one line: a comment, an address, a bug description
- You cannot predict the length in advance
- Line breaks in the answer carry meaning, like a pasted address or a formatted message
- The content deserves more room to compose than a single line gives
Reach for something else when
- The answer fits on a single line, like a name or a subject. Use a text field instead.
- The answer is one of a small, known set of options. Use a select instead.
- Someone is picking several options from a known set, not writing sentences. Use a group of checkboxes instead.
Variants
Autosizing, fixed with manual resize, and a live character count. Type in the third box to watch the count move.
Autosizing. The box grows with the content and stops resizing manually being the person's job. Set a max-height so an extreme answer scrolls inside the box instead of pushing a submit button off the bottom of the screen.
Fixed height, manual resize. A set number of rows with the native resize handle left on. Reasonable for a field where most answers fit the box and the rare long one is fine to drag open.
With a character count. The count sits under the box, updates as they type, and only turns into a warning colour near the limit. It is a piece of information, not a running scoreboard.
States
Default, filled, near the limit, error and disabled. The near-limit count turns colour without changing size, so colour is never the only signal doing the work.
| State | What changes | Watch out for |
|---|---|---|
| Default | 1px border or a filled background, resting height | Border or fill needs 3:1 contrast against the page (WCAG 1.4.11) |
| Focus | Accent border plus a visible ring | Never remove the ring without replacing it with something visible |
| Filled | Value replaces the placeholder | Value text needs higher contrast than placeholder text |
| Near limit | Character count switches to a warning colour | Colour alone fails 1.4.1, so the number itself has to change too, not just its colour |
| Error | Red border, message below, aria-invalid="true" | Same rule as a text field: say what is wrong and what to do |
| Disabled | Reduced opacity, not focusable | Not submitted. State why it is off somewhere nearby |
| Read only | Flat background, no border | Still focusable, still submitted, still selectable |
The near-limit state is the one worth building deliberately. A counter that only appears at zero characters left has already failed. Show it early enough that reaching the limit is a decision, not a surprise.
How a textarea behaves
Tab moves focus out, not text in. Pressing Tab inside a plain textarea should move to the next field, the same as any other input. Trapping Tab to insert a tab character is correct in a code editor and wrong everywhere else, and it is a common accessibility bug in custom-built fields.
Enter always inserts a line break. A textarea has no concept of submitting a form on Enter, which is exactly why it is the wrong choice for a single-line answer that does expect that behaviour.
Growth needs a ceiling. An autosizing box with no max-height will happily grow to the length of a pasted document, taking the rest of the form with it. Cap the height and let the box scroll internally past that point.
Whitespace survives. Line breaks and multiple spaces are part of the value. Trim leading and trailing whitespace on submit, the same as a text field, but leave internal formatting alone.
Pasted content should never be silently cut. If a limit exists, accept the paste in full and show the field over its limit rather than truncating what someone just pasted in.
Textarea accessibility
Keyboard
| Key | What happens |
|---|---|
Tab | Moves focus to the next field. |
Shift + Tab | Moves focus to the previous field. |
Enter | Inserts a line break. Never submits the form from inside a textarea. |
| Arrow keys | Move the cursor within the text, wrapping between lines as expected. |
The rest
- Contrast. The border or fill needs 3:1 against the page at rest (WCAG 1.4.11).
- 16px minimum text size. Same rule as a text field. Safari on iOS zooms the page in on focus if the font is smaller, and the zoom does not reset on blur.
- Label it the same way a text field is labelled. An explicit
<label for>connection, never a placeholder standing in for one. - The resize handle has no keyboard equivalent in most browsers. This does not fail WCAG, because the content stays fully readable through internal scrolling. It is worth knowing rather than assuming keyboard users can drag the corner the way a mouse user does.
What a textarea should say
Labels are nouns. "Cover letter" beats "Write your cover letter here".
Put format guidance in a hint, not a placeholder. "Include your order number if you have it" belongs under the label, where it survives the first keystroke.
Character counts read as a number, not a scold. "420 characters left" or "128 / 500", never "You have used 128 of your 500 characters".
Errors name the field and the fix. "Message must be under 500 characters, you are 40 over" beats "Too long".
Common textarea mistakes
Six rows signals a real answer is expected, and the box still autosizes past that if someone writes more.
A one-row box with resizing switched off for an answer that was always going to run to a paragraph.
The one that shows up constantly is a two-row box for an answer that was always going to run to a paragraph, so every response gets read through a porthole.
1. A fixed, tiny box for an answer with no natural length. Bug reports, cover letters and support messages do not fit in two rows. Size the box to a realistic answer, not the smallest space that technically fits the label.
2. Removing the resize handle from a fixed box with no autosize. That leaves someone stuck viewing four lines of a much longer answer with no way to see more of it.
3. A character counter from the very first keystroke. "0 / 500" on an empty field is pressure with no information in it yet.
4. Placeholder text standing in for the label. It disappears on the first character typed, on the field most likely to hold something someone needs to check back on.
5. Autosizing with no maximum height. A pasted paragraph or a long paste-in of code takes the submit button with it as the box grows without limit.
6. Truncating a paste that exceeds the limit. Silently cutting off the end of what someone just pasted loses content they never saw disappear.
How to build a textarea
<div class="field">
<label for="message">Message</label>
<textarea
id="message"
name="message"
rows="5"
maxlength="500"
aria-describedby="message-count"
style="field-sizing: content; max-height: 320px;"
></textarea>
<p id="message-count">0 / 500</p>
</div>
const textarea = document.getElementById("message");
const counter = document.getElementById("message-count");
textarea.addEventListener("input", () => {
counter.textContent = `${textarea.value.length} / 500`;
});
field-sizing: content autosizes the box with no JavaScript at all. It shipped in Chromium-based browsers first and has been landing across the rest since, so pair it with a max-height and treat a manual scrollHeight resize as the fallback where it is not yet supported.
Edge cases
A single word longer than the box. A pasted URL with no spaces needs overflow-wrap: break-word, or it pushes the field wider than its container.
Zoom to 200 percent. The label, box and hint all need to stay visible and inside the viewport (WCAG 1.4.4).
Right to left. The text and the resize handle both mirror. Use logical properties so the handle ends up in the correct corner without a second stylesheet.
Hidden then shown. An autosizing textarea measured while display: none reports a height of zero. Measure again after it becomes visible, or the box opens collapsed.
A slow save. If the content saves as someone types (a draft), show that state near the field rather than on it, so it does not compete with the text being written.
Textareas in real products
GitHub autosizes its comment and pull request description boxes as you type, keeps the native resize handle active on top of that, and caps growth with an internal scrollbar once a comment gets long.
X (formerly Twitter) shows nothing until you approach its 280-character limit, then a numeric countdown appears and turns red at zero, letting the last characters go slightly negative rather than blocking the keystroke outright.
Linear autosizes an issue's description field with a generous maximum height, switching to internal scrolling for anything longer rather than letting the field crowd the rest of the panel out of view.
Common questions
- How tall should a textarea start?
- Match the height to the answer you expect, not to what fits on the screen. Two to three visible rows for a short comment, five to six for a support message, more for anything meant to read back as a document. A one-row textarea is a text field wearing the wrong component.
- Should a textarea grow as someone types?
- For a single, prominent field, yes. It saves someone from scrolling inside a small box to check what they already wrote. The CSS property field-sizing: content does this natively, with no JavaScript, and is what this site's own textarea uses. Where it is not yet supported, the fallback is resizing the box in a keyup handler to match its scrollHeight.
- Does a textarea need a character limit and counter?
- Only when the destination actually enforces one, like a 280-character post or a fixed database column. Show the count once someone gets within about 20% of the limit, not from the first keystroke. A visible "0 / 500" on an empty field reads as pressure, not information.
- Should I remove the resize handle in the corner?
- Not without giving people another way to see more of what they wrote. That is usually an autosizing box. Removing manual resize from a fixed-height field with no autosize leaves someone stuck reading four lines through a two-line window.
- Textarea or a rich text editor?
- A textarea when the destination stores plain text: a comment, a support message, an address. A rich text editor when formatting is part of the answer itself, like a blog draft. They are different components with different accessibility trees, not the same field with a toolbar bolted on.
Last reviewed 29 JUL 2026
