Standards · ARIA

Role Widget

textbox

Marks an element as a single- or multi-line text input. Use <input type="text"> or <textarea> first — they handle every textbox behaviour for free. Reach for role="textbox" only when building a rich-text editor on a contenteditable element.

When to use

Use <input type="text">, <input type="email">, <input type="url">, <input type="tel">, or <textarea> — whichever matches the input semantics. Native handles selection, the caret, IME composition, form submission, autocomplete tokens, and validation, all of which are very hard to recreate.

role="textbox" is appropriate on one kind of element: a contenteditable div that hosts a rich-text editor. The role tells assistive tech to expose it as an editable region rather than a generic container. Set aria-multiline="true" if the editor accepts multiple lines.

If your “textbox” needs autocomplete suggestions, use role="combobox" on the input instead — textbox does not own a popup.

Common failures

  • role="textbox" applied to a <div> that is NOT contenteditable. The role announces an editable field but typing does nothing.
  • Custom textboxes without a paired <label for> or aria-label — the field has no accessible name.
  • Using placeholder as the only label. Placeholder disappears on focus, fails contrast for many themes, and is not an accessible name.
  • role="textbox" on a single-line contenteditable that does not strip pasted line breaks. Users paste content with newlines that bypass the visual constraint.
  • Missing aria-multiline="true" on a multi-line contenteditable editor — screen readers announce it as a single-line input.

Example

<!-- Preferred -->
<label for="bio">Short bio</label>
<textarea id="bio" rows="4" maxlength="240"></textarea>

<!-- Rich-text editor -->
<label id="commentLabel">Comment</label>
<div
  role="textbox"
  contenteditable="true"
  aria-labelledby="commentLabel"
  aria-multiline="true"
></div>