Accessible Forms Design Guide: Labels, Errors, and WCAG Compliance

Blogguides

Accessible Forms Design Guide: Labels, Errors, and WCAG Compliance

Forms are the most interaction-heavy part of any website. Login, registration, checkout, contact, search — every conversion flows through a form. And forms are where accessibility fails most catastrophically. Missing labels, invisible error messages, broken tab order, focus traps: screen reader users and keyboard-only users hit walls that sighted mouse users never notice. The good news: accessible forms are not hard to build. They just require knowing the rules and applying them consistently.

The Golden Rule: Every Input Needs a Label

This is WCAG 1.3.1 (Info and Relationships) and 3.3.2 (Labels or Instructions). Every form field must have a programmatically associated label. Not just visual text near the input — an actual <label> element with a for attribute matching the input's id.

<!-- Correct -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

<!-- Also correct: wrapping -->
<label>
  Email address
  <input type="email" name="email">
</label>

<!-- WRONG: placeholder is not a label -->
<input type="email" placeholder="Email address">

Placeholder text is not a label. It disappears when the user starts typing, making it impossible to verify what the field is for. Always use a visible, persistent label.

Required Fields

Mark required fields with both a visual indicator (asterisk, text) and the HTML required attribute or aria-required="true". Don't rely on color alone (red asterisk is meaningless without context).

<label for="name">Full name <span aria-hidden="true">*</span></label>
<input type="text" id="name" required aria-required="true">

Add an instruction at the top of the form: "Fields marked with * are required." This helps all users, not just screen reader users.

Use <fieldset> and <legend> to group related fields. This is especially important for radio buttons and checkboxes, where the group label provides essential context.

<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>
  <label><input type="radio" name="contact" value="mail"> Mail</label>
</fieldset>

Without the fieldset/legend, a screen reader announces "Email, radio button" — which email? In what context? The legend provides the missing information: "Preferred contact method, Email, radio button."

Error Handling

Error handling is where most forms fail accessibility. WCAG requires three things:

1. Identify the error (WCAG 3.3.1)

When a form validation fails, tell the user which field has the error and what's wrong. Not just "Please fix errors" — specifically: "Email: Please enter a valid email address."

2. Describe the error in text (WCAG 3.3.3)

Error messages must be in text, not just icons or color changes. A red border around the field means nothing to a screen reader user.

3. Associate errors with fields (WCAG 1.3.1)

Use aria-describedby to link the error message to the input field:

<label for="email">Email address</label>
<input type="email" id="email" aria-describedby="email-error" aria-invalid="true">
<p id="email-error" class="error">Please enter a valid email address.</p>

The aria-invalid="true" attribute signals to assistive technology that the field contains an error. The aria-describedby associates the error text with the field.

Error Summary

For forms with multiple errors, add an error summary at the top of the form with links to each invalid field. Move focus to the summary when the form is submitted with errors. This is WCAG 3.3.1 best practice.

<div role="alert" aria-labelledby="error-heading">
  <h2 id="error-heading">2 errors found</h2>
  <ul>
    <li><a href="#email">Email: Please enter a valid address</a></li>
    <li><a href="#phone">Phone: Please enter a 10-digit number</a></li>
  </ul>
</div>

Keyboard Navigation

Every form interaction must work with keyboard alone. This means:

  • Tab order: follows the visual layout (left to right, top to bottom). Don't use tabindex values greater than 0.
  • Focus visible: every focused element must have a visible focus indicator. Never outline: none without a replacement.
  • No focus traps: the user must be able to Tab into and out of every element. Date pickers and custom dropdowns are common offenders.
  • Submit with Enter: pressing Enter in a text field should submit the form (default HTML behavior — don't break it with JavaScript).

Custom Controls and ARIA

If you build custom form controls (custom dropdowns, toggle switches, sliders), you must add ARIA roles and properties to make them accessible. The WAI-ARIA Authoring Practices guide provides patterns for every common widget.

A few rules of thumb:

  • Prefer native HTML elements over custom ones. A <select> is already accessible. A <div class="dropdown"> is not.
  • If you must build custom: add role, aria-expanded, aria-selected, keyboard event handlers (arrow keys, Enter, Escape).
  • Test with a screen reader. NVDA (free, Windows), VoiceOver (built-in, macOS/iOS), TalkBack (Android).

WCAG 2.2 New Requirements for Forms

WCAG 2.2 added several success criteria relevant to forms:

  • 3.3.7 Redundant Entry (A): don't ask users to re-enter information they've already provided in the same session. Auto-fill shipping address from billing address.
  • 3.3.8 Accessible Authentication (AA): login must not rely on cognitive function tests (CAPTCHA). Provide alternatives: passkeys, magic links, biometric.
  • 2.4.11 Focus Not Obscured (AA): the focused element must not be hidden behind sticky headers or footers. Ensure focus is visible at all times.
  • 3.2.6 Consistent Help (A): if help is available (chat widget, FAQ link), it must be in the same relative position across pages.

Testing Checklist

  1. Tab through the entire form with keyboard only — is every field reachable? Is focus visible?
  2. Submit the form empty — are error messages clear, specific, and linked to fields?
  3. Test with a screen reader (NVDA or VoiceOver) — are labels announced? Are errors announced?
  4. Test with browser zoom at 200% — does the form remain usable?
  5. Check contrast ratios for labels, placeholder text, and error messages
  6. Verify autocomplete attributes for common fields (name, email, address, credit card)

Najczęściej Zadawane Pytania

Is placeholder text accessible?

Screen readers can read it, but it fails as a label because it disappears. Always use a persistent visible label.

Do I need ARIA for standard HTML forms?

Not for standard elements with proper labels. ARIA is needed for custom controls, error messages, and dynamic content.

How do I make CAPTCHA accessible?

Use invisible reCAPTCHA v3, hCaptcha accessibility mode, or eliminate CAPTCHA with rate limiting and honeypot fields.

Scan Your Website for Free

Get an instant WCAG 2.1 compliance report, no signup required

Start Free Scan