Accessible form validation and error messages
Updated October 14, 2026 · 6 min read
Checkout and registration forms are where shops lose customers, and error handling is where forms most often fail people using screen readers, magnification or keyboard. The rule is simple: say what is wrong, in text, next to the field, and make sure assistive technology hears it. This page is part of the accessible UI patterns series.
Relevant WCAG criteria
- 3.3.1 Error Identification (A): "the item that is in error is identified and the error is described to the user in text". W3C adds that colour may be used, but only in addition to the text.
- 3.3.3 Error Suggestion (AA): if an error is detected automatically and a correction is known, suggest it, unless that would jeopardise security or the purpose of the content. "Email is not valid" meets 3.3.1; "Enter an email address in the format [email protected]" also meets 3.3.3.
- 3.3.2 Labels or Instructions (A): say in advance what is required and in which format.
- 4.1.3 Status Messages (AA): W3C's own example is text "5 errors on page" added to a form without moving focus — it must be announced. A message that receives focus is a change of context and not a status message.
- 3.3.4 Error Prevention (Legal, Financial, Data) (AA): orders must be reversible, checked or confirmed before they are final.
- 1.4.1 Use of Color (A), 1.4.3 Contrast (Minimum) (AA): red text on white must still reach 4.5:1.
- 3.3.7 Redundant Entry (A): after an error, do not make users re-enter data they already gave.
Code example
<form novalidate>
<div id="error-summary" tabindex="-1" aria-labelledby="error-summary-title" hidden>
<h2 id="error-summary-title">2 errors in the form</h2>
<ul>
<li><a href="#email">Email: enter an address in the format [email protected]</a></li>
<li><a href="#postcode">Postcode: enter it in the format 00-950</a></li>
</ul>
</div>
<label for="email">Email</label>
<input id="email" type="email" autocomplete="email"
aria-invalid="true" aria-describedby="email-error">
<p id="email-error" class="error">
<span aria-hidden="true">⚠</span> Enter an address in the format [email protected]
</p>
<label for="postcode">Postcode <span class="hint" id="postcode-hint">(for example 00-950)</span></label>
<input id="postcode" autocomplete="postal-code"
aria-invalid="true" aria-describedby="postcode-hint postcode-error">
<p id="postcode-error" class="error">Enter the postcode in the format 00-950</p>
<button type="submit">Continue to payment</button>
</form>
How it works:
- Text, next to the field. Each message is visible text, connected with
aria-describedbyso it is read with the field.aria-invalid="true"marks the field as invalid — W3C technique ARIA21 "Using aria-invalid to Indicate An Error Field". - Error summary on submit. Show a summary at the top with links to the fields and move focus to it (it has
tabindex="-1"so it can receive focus), or move focus to the first invalid field. If you do not move focus, announce the errors with a live region instead — W3C technique ARIA19, "Using ARIA role=alert or Live Regions to Identify Errors". Do not do both, or the message is read twice. - Inline validation while typing should be gentle: validate when the user leaves the field, not on every keystroke, and remove the error as soon as it is fixed.
- Keep the data. After a failed submit, keep everything the user entered.
- Native browser validation (
required,type="email") works too, but its messages and styling vary by browser and language; many shops usenovalidateand their own messages in the page language.
Keyboard and focus behaviour
| Action | Expected result |
|---|---|
| Submit with errors | Focus moves to the error summary (or the first invalid field); the screen reader reads it |
| Enter on a link in the summary | Focus moves to the field; label, invalid state and message are read |
| Tab out of a field with an error (inline validation) | Message appears in text; announced through aria-describedby when the field is focused again, or as a status message |
| Correcting the field | aria-invalid is removed; the message disappears |
Common mistakes on online shops
- Only a red border around the invalid field, or a red asterisk with no text.
- Errors as a toast at the top of the screen that disappears after three seconds and is never announced.
- Generic messages — "Invalid input", "Error" — with no hint what format is expected.
- Placeholder as the only label and format hint, which disappears as soon as the user types.
- Messages not linked to fields, so screen reader users hear the label and nothing else.
- Submit button disabled until the form is valid, hiding the problem instead of explaining it; see disabled buttons.
- Payment provider iframes with their own unlabelled fields and English-only errors on a localised shop.
- The form is cleared after a server-side error, including the delivery address.
What automated checks catch vs manual testing
| Automated (axe-core rule) | What it finds |
|---|---|
label, select-name |
Fields without a label |
label-title-only |
Fields labelled only by title or aria-describedby (advice) |
form-field-multiple-labels |
Fields with more than one label |
autocomplete-valid |
Invalid autocomplete values on personal data fields (1.3.5) |
aria-valid-attr-value |
aria-describedby pointing to a missing ID, invalid aria-invalid values |
color-contrast |
Error text with too little contrast, when it is visible |
frame-title |
Payment iframes without a title |
All are cards in our rule library. The automated check sees the form in its initial state; it does not submit it. Test manually: submit empty and wrong values, check that every error is described in text, linked to its field, announced by a screen reader and readable at 200% zoom. With the browser extension you can run the automated rules again while the errors are on screen. The steps are in how to test WCAG.
Run the free one-page check on your checkout or contact page. It is an automated check, not a full audit.
Frequently asked questions
What does WCAG require for form errors?
3.3.1 Error Identification (A): the field in error is identified and the error is described in text. 3.3.3 Error Suggestion (AA): if a correction is known, suggest it. 4.1.3 Status Messages (AA): messages that appear without moving focus are announced by assistive technology.
Is a red border enough to show an error?
No. W3C says colour may be used in addition, but the error must also be identified in text. A red border alone fails people who cannot see colour and screen reader users.
How do I connect an error message to a field?
Give the message an id and reference it from the input with aria-describedby, and set aria-invalid="true" on the field (W3C technique ARIA21). The screen reader then reads the label, the invalid state and the message.
Should focus move to the first error?
On submit, moving focus to an error summary or to the first invalid field is a common and robust approach. If focus does not move, a message such as "3 errors in the form" must be a status message so it is announced.
Can an automated check test form errors?
It checks the form in its initial state: labels, autocomplete values, valid ARIA references and contrast. It does not submit forms, so whether errors appear, are described in text and are announced must be tested manually.
Sources
- W3C, Understanding 3.3.1 Error Identification: https://www.w3.org/WAI/WCAG22/Understanding/error-identification.html
- W3C, Understanding 3.3.3 Error Suggestion: https://www.w3.org/WAI/WCAG22/Understanding/error-suggestion.html
- W3C, Understanding 4.1.3 Status Messages: https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html