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.