Error Identification
If an input error is automatically detected, the item in error is identified and the error is described to the user in text.
Who this affects
Screen reader users, who cannot see a red border. Colour-blind users, for whom red-only marking is invisible. Anyone who needs to know which of fifteen fields is wrong and why.
The failure and the fix
Each example below is a self-contained page, loaded in a frame so its markup cannot affect this page. Open either one on its own to test it with a keyboard or screen reader.
Fails 3.3.1
Open the failing example in a new tab
fail.html — the problem
<h1>Create your account</h1>
<form id="signup" novalidate>
<div class="field">
<label for="email">Email address</label>
<input type="email" id="email" name="email">
</div>
<div class="field">
<label for="pw">Password</label>
<input type="password" id="pw" name="pw">
</div>
<!-- FAILURE: on submit the script marks bad fields with a red border and
nothing else. There is no text describing the error, no programmatic
link between the message and the field, and no announcement.
A screen reader user hears silence and has no idea what went wrong,
or which of the two fields is the problem. Colour is the only signal,
which also fails 1.4.1 Use of Color. -->
<button type="submit" class="button">Create account</button>
</form>
Meets 3.3.1
Open the passing example in a new tab
pass.html — the fix
<h1>Create your account</h1>
<!-- FIX 1: an error summary at the top of the form. It is focused after a
failed submit, so a screen reader reads the whole problem immediately, and
each entry links to the field that caused it. tabindex="-1" makes it
focusable by script without adding it to the tab order. -->
<div id="summary" class="error-summary" role="alert" tabindex="-1" hidden>
<h2>There is a problem</h2>
<ul id="summary-list"></ul>
</div>
<form id="signup" novalidate>
<div class="field">
<label for="email">Email address</label>
<!-- FIX 2: aria-describedby ties the message to the field, so moving focus
to the input reads the label AND the error. aria-invalid marks the
state, so the field announces as "invalid entry". -->
<input type="email" id="email" name="email" aria-describedby="email-err">
<p class="error-text" id="email-err" hidden></p>
</div>
<div class="field">
<label for="pw">Password</label>
<input type="password" id="pw" name="pw" aria-describedby="pw-err">
<p class="error-text" id="pw-err" hidden></p>
</div>
<button type="submit" class="button">Create account</button>
</form>
How to test it
Submit a form with deliberate errors. Confirm each error is described in text, names the specific field, and is programmatically associated with it via aria-describedby, and that the error is announced.
-
Automated
Scanners check aria-invalid and aria-describedby wiring when errors are present, but must be driven into the error state first — a static scan of a clean form finds nothing.
This demo's failure is not machine-detectable. The errors are signalled with a CSS class and a red border. There is no aria-invalid and no message for axe to validate, so there is nothing for a rule to fire on. A scanner also has to be driven into the error state first: scanning the clean, unsubmitted form finds nothing no matter how broken the error handling is.
Relevant axe rules:
aria-valid-attr-value
-
Keyboard
Unplug the mouse. Move through the page with Tab, Shift+Tab, Enter, Space and the arrow keys. See the keyboard testing script.
-
Screen reader
Listen to both examples with NVDA, JAWS, VoiceOver or TalkBack and compare what is announced. See the screen reader cheat sheets.
-
Visual
Zoom to 200% and 400%, narrow the viewport to 320 px, and apply the text-spacing overrides. See the visual testing procedures.
Related criteria
In the specification
- Understanding 3.3.1 Error Identification — the W3C explanation, intent and exceptions
- 3.3.1 in the WCAG 2.2 Recommendation — the normative wording
WCAG 2.2 Demo Suite