Skip to content
UT Studio

How to build accessible forms

Labels, errors, grouping and autofill — the details that decide whether a form can be completed at all.

UT Studio7 min read

Forms are where accessibility failures cost the most, because a form that cannot be completed is a transaction that does not happen. Most of the failures come from the same handful of decisions.

A label is not a placeholder

Placeholder-as-label fails four ways at once: it disappears as soon as typing begins, it usually fails contrast, it is not reliably announced, and it leaves nothing to click.

A complete field
<div>
  <label htmlFor="email">Email address</label>
  <input
    id="email"
    name="email"
    type="email"
    autoComplete="email"
    aria-describedby="email-hint"
  />
  <p id="email-hint">We send your licence key here.</p>
</div>

Errors must be associated, not merely adjacent

Red text under an input is invisible to a screen reader unless it is connected to the field. `aria-describedby` connects it; `aria-invalid` marks the state.

Associated error
<input
  id="email"
  aria-invalid={error !== undefined}
  aria-describedby={error === undefined ? "email-hint" : "email-error"}
/>
{error !== undefined && (
  <p id="email-error" role="alert">{error}</p>
)}

Do not move focus to the first error on submit

It sounds helpful and it disorients: the page jumps and the user loses their place. Announce the count in a live region and let them navigate.

Radio groups and checkbox sets need a `fieldset` and a `legend`. Without them, a screen reader announces "Standard, radio button" with no indication of what question it answers.

Grouped inputs
<fieldset>
  <legend>Delivery speed</legend>
  <label><input type="radio" name="speed" value="standard" /> Standard</label>
  <label><input type="radio" name="speed" value="express" /> Express</label>
</fieldset>

Let autofill work

Correct `autocomplete` values are the highest-value five minutes in any form. They help everyone, and they disproportionately help people for whom typing is difficult.

Fieldautocomplete
Full namename
Emailemail
Address line 1address-line1
Postcodepostal-code
Countrycountry-name
New passwordnew-password

Required, and how to say so

Use the `required` attribute rather than an asterisk and a legend. Mark the shorter set: if most fields are required, mark the optional ones instead.

The five-minute check

  1. Complete the form using only the keyboard.
  2. Click each label and confirm focus moves to its field.
  3. Submit it empty and read the errors with the screen reader on.
  4. Zoom to 200% and check nothing is clipped.
  5. Test autofill with a saved profile.

Templates with substantial form surfaces

Templates mentioned here

Everything above is written against real products. These are the ones this page draws on.

Read next