textarea
A textarea lets people write text that runs over several lines, in a square box they can drag taller. Put it in a field for its label, hint and error.
when to use
- For text that runs past one line: a description, release notes, a comment, a config someone pastes in.
- Inside a field, which gives it a label and connects its hint and its error to it.
when to use something else
- For one line. Use an input. A name, a host or a number doesn't need the room, and enter in a textarea adds a line instead of sending the form.
- To show text that people only read or copy, such as a log or a generated config. Use code as a block. A box people can type in suggests that the text can be changed.
- To pick from known values. Use a select.
- To lay out a whole form. Start from forms and settings.
anatomy
- Box. A square with a thin grey border on a dark background, with room inside, as wide as its container.
- Text. What people type, in monospace. The placeholder, when there is one, is dimmer.
- Resize handle. The browser's own, in the bottom-right corner. It drags up and down only.
variants and states
There is one size. The height comes from the number of lines the box shows, four by default, and people can drag it taller. Set the number of lines to the length you expect: two for a short note, eight for a pasted config.
| state | looks |
|---|---|
| At rest | A grey border |
| Focused | A thicker blue border, whenever it has focus, from a click or from the keyboard |
| Invalid | A red border, in the error colour, also while it is focused |
| Disabled | Faded. It can't be focused or edited, and it isn't sent with the form |
| Read-only | Looks as it does at rest. It can be focused, selected and sent with the form, but not edited |
Line 1: name is empty
behaviour
- The textarea is one tab stop. enter starts a new line and never sends the form; tab moves on, rather than typing a tab character.
- No character count is built in. A length limit stops typing at the limit, and cuts pasted text short without a word. State the limit in the hint, and show a count when people are likely to reach it.
59 / 120 characters
The full keyboard map is on the textarea's React page.
accessibility
- Give it a visible label. A field shows one, and connects the hint or the error to the textarea, so a screen reader reads them with it. A placeholder is not a label.
- Say in words what is wrong. An invalid textarea turns its border red, but the colour doesn't say what is wrong. For structured text, name the line: “Line 2: name is empty”.
- Put a length limit in the hint, so it is read with the field. The limit itself is not announced.
- Focus shows in the border, which turns blue and thicker, not with the outline that other controls show. Interaction explains it.
Today: there are no styles for forced colours, the high-contrast setting some operating systems offer. The textarea removes the browser's focus outline and shows focus with a border colour and an inner shadow, which forced colours replace, so a focused textarea can look unfocused there.
content
- Label. A noun for what goes in, in sentence case: “Release notes”, “Description”, “Manifest”.
- Placeholder. An example of a first line, or nothing. Instructions go in the hint, where they stay in view while people type.
- Hint. What the text is for, and its limit: “Shown on the release page. Up to 500 characters.”
- Error. What is wrong, and where: “Line 3: replicas must be a number”.
do and don't
do
Shown on the release page. Up to 500 characters.
don't
do
don't
related
- Input: the same field, for one line.
- Field: the label, hint and error around the textarea.
- Code: text to read or copy, not to edit.
- Forms and settings: where text fields sit in a form.
specs
| state | spec |
|---|---|
| At rest | A 1px --border-control border |
| Focused | On :focus, from the mouse or the keyboard: a --cloud-blue border and a 1px inset --cloud-blue shadow, 2px in all. The browser's outline is removed (outline: none); it doesn't use the --focus-ring outline |
| Invalid | invalid, which a field's error sets, and which sets aria-invalid="true": a --state-error border; while focused, a 1px inset --state-error shadow as well |
| Disabled | disabled: 50% opacity, a not-allowed cursor |
| Read-only | The native readOnly: looks as at rest |
- Box: a native
textarea, square (border-radius: 0),width: 100%, a 1px border on--bg-2, padding 12px. - Text: JetBrains Mono 13px, line height 1.5, in
--fg. The placeholder is--fg-dim. - Height:
rows, 4 by default.resize: vertical, so the handle drags vertically only. - Limit: the native
maxLength. Link a count to the textarea witharia-describedby, as the live example with a limit does. - Label: a field renders a
labelfor the textarea and links its hint or error witharia-describedby. - Motion: the border and the shadow change in 120ms
ease.