Forms & Accessible Error Handling

Web Accessibility — Forms & Accessible Error Handling
Web Accessibility (a11y)
Chapter 5 · Forms & Accessible Error Handling

📝 Forms & Accessible Error Handling

Chapter 4 covered keyboard navigation generally. Forms are where accessibility most commonly breaks down in real-world sites — this chapter covers the specific, well-established patterns that fix it.

Label/Input Association Is Load-Bearing

<label for="email">Email address</label> <input id="email" type="email">

A matched <label for>/id pair isn't a nice-to-have — clicking the label text focuses the input (a larger click target, helping motor disabilities too), and a screen reader announces the label the moment the input receives focus. Without it, an input is announced as just "edit text," with no indication of what it's for.

🚫 The Placeholder-as-Label Anti-Pattern

Placeholder Alone vs a Real Label

Placeholder Only

Disappears the moment typing starts (losing the field's purpose exactly when reviewing it matters most), typically lower contrast by default, and unreliably announced — or not announced at all — by screen readers.

Real <label>

Always visible, always announced, always contrast-compliant text — works correctly for everyone, no exceptions.

If a visually minimal design is genuinely wanted, use a visually-hidden label class — never remove the label element itself.

Fieldset/Legend for Grouped Controls

A Labeled Radio Group

<fieldset> <legend>Preferred contact method</legend> <label><input type="radio" name="contact" value="email"> Email</label> <label><input type="radio" name="contact" value="phone"> Phone</label> </fieldset>

A screen reader announces the <legend> as the user navigates into the group — "preferred contact method" — before hearing each individual option, essential context that a plain nearby visual heading with no programmatic connection would never provide.

❌ Accessible Error Handling

An Invalid Field, Correctly Wired

<label for="email">Email address</label> <input id="email" type="email" aria-invalid="true" aria-describedby="email-error"> <span id="email-error">Enter a valid email address, like name@example.com</span>

aria-invalid

Announces the invalid state itself to a screen reader — not just a visual red border sighted users notice.

aria-describedby

Programmatically links the field to its specific error text, so the message is announced whenever the field is reached — not just displayed nearby with no connection.

Error messages should be specific and actionable, not just "invalid input" — Chapter 1's Understandable principle applies directly here. On a failed submission, move focus to the first invalid field (or an error summary), rather than leaving the user unaware anything went wrong — a direct extension of Chapter 4's focus-management theme.

💻 Coding Challenges

Challenge 1: Fix a Placeholder-Only Field

Given <input type="text" placeholder="Full name"> with no label, rewrite it with a proper <label>.

Goal: Practice the single most common form-accessibility fix.

→ Solution

Challenge 2: Group a Checkbox Set

Given three unlabeled checkboxes for "Email me updates," "SMS me updates," and "Push notifications" with a nearby but unconnected visual heading "Notification preferences," wrap them correctly using <fieldset>/<legend>.

Goal: Practice applying fieldset/legend to a realistic checkbox group.

→ Solution

Challenge 3: Wire Up an Accessible Error

A password field fails validation with the message "Password must be at least 8 characters." Write the complete, correctly-associated HTML for the input and its error message.

Goal: Practice combining aria-invalid and aria-describedby correctly in one example.

→ Solution

⚠️ Gotcha: Reaching for aria-label Instead of a Visible Label

It's tempting to add aria-label to satisfy an accessibility checklist or scanner, when a genuinely visible <label> would have been just as easy to add and serves far more people. aria-label only helps screen reader users — it does nothing for users with cognitive disabilities, low vision, or anyone who simply benefits from seeing what a field is for rather than inferring it from context. A visible label serves everyone at once; reserve aria-label for cases where a visible label genuinely isn't appropriate (a well-known icon-only search field, per Chapter 3), not as a default shortcut to make an automated test pass.

🎯 What's Next

With forms covered, the next chapter turns to what's actually visible: Color, Contrast & Visual Design — WCAG contrast ratios, never relying on color alone, and respecting reduced-motion preferences.