skip to content
menu
components · textarea

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

  1. Box. A square with a thin grey border on a dark background, with room inside, as wide as its container.
  2. Text. What people type, in monospace. The placeholder, when there is one, is dimmer.
  3. 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.
The limit in the hint is read with the field, and stays in view while people type.
don't
An instruction in the placeholder vanishes on the first keystroke.
do
One line of text is an input.
don't
A textarea for one value invites line breaks that the value can't hold.
  • 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 with aria-describedby, as the live example with a limit does.
  • Label: a field renders a label for the textarea and links its hint or error with aria-describedby.
  • Motion: the border and the shadow change in 120ms ease.