Tags: ux web-dev concept

Accessible Forms

Date: 2026-08-17


Forms are where accessibility failures block transactions outright. Nearly all of it is three things — a real label, an error someone can perceive, and a grouping that makes sense read aloud — and all three are native HTML.


An accessible form can be completed by someone using a keyboard, a screen reader, magnification, or voice control. A form that can’t be completed is a blocked purchase, which is where legal and commercial risk both concentrate — Accessibility Law in the UK.

Labels

The single most important requirement.

<!-- explicit — preferred -->
<label for="postcode">Postcode</label>
<input id="postcode" name="postcode">
 
<!-- implicit — also valid -->
<label>
  Postcode
  <input name="postcode">
</label>

A placeholder is not a label. An input with only a placeholder is announced as “edit text, blank” once focused, and the hint disappears the moment typing starts — Form Design.

Voice control depends on the visible label too. “Click Postcode” only works if the visible text matches the accessible name — which is why aria-label overriding a different visible label breaks voice users.

Grouping

Radio buttons and checkboxes need their question announced, or the options are meaningless:

<fieldset>
  <legend>Delivery speed</legend>
 
  <input type="radio" id="std"
         name="speed" value="standard">
  <label for="std">Standard — free</label>
 
  <input type="radio" id="exp"
         name="speed" value="express">
  <label for="exp">Express — £4.95</label>
</fieldset>

Without the <fieldset> and <legend>, a screen reader announces “Standard, free, radio button, 1 of 2” with no indication of what’s being chosen.

Hints and descriptions

<label for="pw">Password</label>
<input id="pw" type="password"
       aria-describedby="pw-hint">
<p id="pw-hint">
  At least 12 characters
</p>

aria-describedby associates supplementary text so it’s announced with the field. Requirements stated only visually are invisible to a screen reader user until the error fires.

Errors

<label for="email">Email</label>
<input id="email" type="email"
       aria-invalid="true"
       aria-describedby="email-err">
<p id="email-err">
  <svg aria-hidden="true">…</svg>
  Enter an email address in the
  format name@example.com
</p>
aria-invalid="true"     announces the
                        field as invalid
aria-describedby        links the message
ICON + TEXT             not colour alone
                        — Colour Contrast
SPECIFIC WORDING        what's wrong and
                        how to fix it

See: Colour Contrast

On submit failure, move focus to an error summary at the top, listing each error as a link to its field:

<div role="alert" tabindex="-1"
     id="errors">
  <h2>There is a problem</h2>
  <ul>
    <li><a href="#email">
      Enter a valid email address
    </a></li>
  </ul>
</div>

This pattern is the single most effective accessible-forms technique — it announces the failure, states the count, and provides a route to each field — Focus Management, Error Prevention and Recovery.

Required fields

<label for="name">
  Name <span aria-hidden="true">*</span>
</label>
<input id="name" required
       aria-required="true">

required is announced by screen readers. The asterisk is a visual convention that needs a legend — and marking the smaller set is clearer for everyone.

Autocomplete

<input autocomplete="given-name">
<input autocomplete="address-line1">
<input autocomplete="postal-code">

This is a WCAG criterion, not only a convenience. Correct autocomplete values let assistive technology and browsers identify a field’s purpose, which supports both autofill and personalisation tools that relabel fields with icons or simpler language — Cognitive Accessibility.

Where it goes wrong

  • Placeholder-only labels, the most common failure
  • Custom controls without roles. A styled div acting as a select, with no keyboard support
  • Errors announced only visually
  • Errors appearing above the fold while focus is below — nobody sees them
  • Timeouts on checkout without warning or extension
  • CAPTCHA with no accessible alternative — a hard block
  • Third-party payment iframes that trap focus or lack labels, which are still your problem — Third-Party Scripts

Testing

1  Tab through the whole form
2  is every field labelled aloud?
3  submit it empty — is the failure
   announced, and is focus moved?
4  fix one error — is the change
   announced?
5  complete a purchase, keyboard only

Step 5 is the acceptance test. Everything else is diagnosis — Keyboard Navigation, Screen Readers.