Understanding WCAG 3.3.1
What is it?
When a form rejects what you typed, you need to know three things:
- That an error occurred
- Where the error is
- What the error is
…in text, and ideally programmatically tied to the input, not just a red form field or an alert icon.
Why it matters
Sighted users can see a red border and understand “this is where the problem is.” Everyone else gets nothing.
A form that doesn’t tell you what went wrong is a form you can’t finish.
Users give up, abandon the task, or have to ask for help with something that should have taken a few seconds.
Who it affects
People who…
- use screen readers
- have low vision
- have color blindness
- browse with high-contrast mode, custom stylesheets, or browser extensions that strip color
- are tired, distracted, or filling out the form on small screens
Common Failures
1. Color-only error indication
A red border, background, or icon with no text. Users who can’t perceive color can’t tell anything is wrong.
(This also fails 1.4.1 Use of Color.)
2. Error text visible but not tied to the input
Screen reader users hear the label but no error message when the input gets focus. The visible “Email address is required” text exists on the page, but there’s no aria-describedby connection between the input and the message.
3. Generic “Please fix the errors below”
The form summary says something is wrong but doesn’t say what or where. Users have to guess what the problem is. In a 40-field form, this is its own special kind of cruelty.
4. Icons without alternative text
A red X near the input, with no accessible name. Sighted users see the icon. Screen readers hear only “Email address, edit text” with no indication that anything is wrong.
5. Errors that show up silently after submit
The user presses submit. Error messages appear visually next to the broken fields. Focus stays on the submit button. The screen reader says nothing. Screen reader users won’t know anything changed.
6. Custom validation that drops the semantics
The browser’s built-in semantics are gone without a replacement. Visual styling is applied, but semantic information and focus management are missing.
Example of what NOT to do:
form.addEventListener('submit', e => {
if (!email.value.trim()) {
e.preventDefault();
email.classList.add('error');
errorMsg.style.display = 'block';
}
});
No focus change, no announcement of errors for screen readers.
Solutions
Pair every visual cue with a text message
- Bad: red border on the input, nothing else.
- Better: red border plus visible “Email address is required” text.
- Best: red border plus “Email address is required. Use the format [email protected].” (Bonus: this also addresses 3.3.3 Error Suggestion.)
Tie the error to the input
Use aria-describedby to connect the input to its error message.
<label for="email">Email address</label>
<input
id="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
required
>
<p id="email-error" class="error">
Email address is required. Use the format [email protected].
</p>
Announce errors that appear after submit
If error messages are added to the page after the user submits, put them in a region with role="alert" and/or move keyboard focus to an error summary at the top of the form.
<div role="alert" tabindex="-1">
<h2>There were 3 problems with your submission</h2>
<ul>
<li><a href="#email">Email address is required</a></li>
<li><a href="#phone">Phone number must be 10 digits</a></li>
<li><a href="#zip">ZIP must be 5 digits</a></li>
</ul>
</div>
Each error in the list links directly to the input that needs fixing.
Render the alert container on page load (empty), then populate it on submit. Newly-injected role="alert" elements aren’t announced reliably.
For inline validation, slow down before announcing
Live validation that fires on every keystroke creates a wall of noise for screen reader users. Wait until blur, or until the user has paused typing, before announcing the error.
How to test
- Submit a form with errors using a screen reader. Does it tell you what went wrong, where, and how to fix it?
- Turn off CSS in DevTools and submit. Are the errors understandable as plain text?
- Tab through the form after submitting. Does each input announce its error when it gets focus?
- Scan with AAArdvark. It can flag help text and error messages that aren’t associated with their inputs.
Closing
A form that fails silently is a form that gives up halfway. Tell people what went wrong, point to where it went wrong, and give them a clear way out.
3.3.1 isn’t about being polite. It’s about giving every user the same chance to finish what they started.
Learn more
Want more clear and actionable WCAG breakdowns? Check out WCAG in Plain English.