Accessible forms
Most accessibility money is lost in forms. A label that is only a placeholder, an error announced only in red — each is a small thing, and together they are a checkout nobody can complete.
What goes wrong
The label is not a label. A placeholder, or text sitting visually next to the field with no programmatic association. The field is announced as “edit text, blank” and the person has to guess from position.
The error is only visual. The message renders in red beside the field. It is not associated with the input, not in a live region, and focus does not move. A screen reader user presses submit and hears nothing at all — the form appears to have simply not worked.
The error says nothing useful. “Invalid input” states a condition. The person needs the remedy: the expected format, the allowed range, the reason it was rejected.
Required is signalled by colour. A red asterisk with no text equivalent and no required attribute.
The field does not declare its purpose. No autocomplete, so browser autofill cannot help — which is an accessibility feature before it is a convenience, because it removes typing for people with motor and cognitive disabilities.
How to test it
Submit every form wrong, on purpose, with a screen reader running.
- Submit it completely empty.
- Submit with one field malformed — a bad email, a short password, a wrong card.
- Listen. Was anything announced? Could you find the field it refers to without looking?
- Tab to each field with your eyes closed. Does what you hear tell you what to type?
- Check that your browser’s autofill offers to complete name, email and address.
How to fix it
Associate every label.
<!-- The placeholder vanishes and is not a label -->
<input type="email" placeholder="Email address" />
<!-- Announced, clickable, and still there after typing -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" autocomplete="email" />
Tie errors to their field, and announce them.
<label for="card">Card number</label>
<input
type="text"
id="card"
name="card"
inputmode="numeric"
autocomplete="cc-number"
aria-invalid="true"
aria-describedby="card-error"
/>
<p id="card-error" role="alert">
Enter the 16 digits on the front of the card, without spaces.
</p>
Three things are doing work there. aria-invalid exposes the state. aria-describedby means the message is read when the field receives focus. role="alert" means it is announced when it appears.
On submit, move focus. Either to the first field in error, or to an error summary at the top of the form that lists each problem as a link to its field. The summary scales better for long forms and is the pattern most public-sector guidance recommends.
Say how to fix it, not that it is wrong. “Enter a date in the future” beats “Invalid date”. “Passwords need at least 10 characters” beats “Password does not meet requirements”.
Never block paste. Blocking paste in a password or card field breaks password managers and is a barrier under 3.3.8 Accessible Authentication.
Why it matters commercially
This is the category where accessibility work pays for itself without reference to the law. A checkout that announces its errors properly has a lower abandonment rate for everybody, because everybody occasionally submits a form wrong — and the difference between “your card was declined” and silence is a difference every customer feels.