Module 35: Forms and Validation in React
Accessible forms
🏠The everyday picture
A ramp, braille signs and a hearing loop make a building usable by more people, without making it worse for anyone. Forms need their own ramps.
📘What it really is
Everything from Modules 12 and 13 applies in React, plus a few connections only code can make:
- Every input has a visible
<label htmlFor>matching itsid. - Connect error messages to their fields, so screen readers read them with the field:
<input
id="email"
name="email"
type="email"
value={form.email}
onChange={handleChange}
onBlur={() => setTouched(t => ({ ...t, email: true }))}
aria-invalid={Boolean(showError("email"))}
aria-describedby={showError("email") ? "email-error" : undefined}
/>
{showError("email") && <p id="email-error" className="error">{errors.email}</p>}
aria-invalidtells assistive technology the field has a problem.-
Announce results like "Enquiry added" in an element with
role="status"(oraria-live="polite"), so they're read out without moving focus. -
Don't rely on colour alone: error text, not just a red border.
- Test with the keyboard only (Tab, Shift+Tab, Enter) and run Lighthouse (Module 12).
useId()creates unique ids for labels and descriptions, useful when a form component is used more than once on a page.
🖱️Try it
Add aria-invalid and aria-describedby to every field, and put the confirmation message in a role="status"
element. Complete the whole form using only the keyboard. Run Lighthouse's accessibility check and fix what it
reports.
✅Quick check
What does aria-describedby="email-error" do?
Show the answer
It links the field to the error message, so screen readers read the error along with the field.
Is a red border enough to show an error?
Show the answer
No. Some people can't see colour differences; show error text too.
