Accessible Ariel

Accessible Forms

W3C WAI form tutorial topics: labeling, grouping, instructions, validation, notifications, and custom controls.

The Rules

Click any rule to expand it. Tags show which W3C WAI section it covers.

Demo: Labeling Controls

Labeling Controls

A visible <label> linked with htmlFor gives every input an accessible name. Placeholders are never a substitute.

✓ Correct

✗ No label

Demo: Grouping Controls

Grouping Controls

Radios, checkboxes, and related fields need semantic grouping so screen readers announce the group name alongside each control.

Radio buttons → <fieldset> + <legend>

Output format

Checkboxes — also need <fieldset> + <legend>

I want to receive

Select with <optgroup>

Related text fields → role="group" + aria-labelledby

Shipping Address
Billing Address
Demo: Custom Controls

Custom Controls

When native elements won't do, add role, aria-checked, and keyboard handlers so custom widgets behave like their native counterparts.

Star rating → role="radiogroup" + role="radio" + arrow key navigation

Toggle switch → role="switch" + aria-checked

Demo: Instructions + Validation + Notifications

Full Form — All Together

Pre-form instructions, fieldset grouping, inline hints, aria-invalid, a focusable error summary, and a live-region success message. Submit empty to see validation in action.

Before you begin:
  • Fields marked with an asterisk are required.
  • Email must be a valid address, e.g. you@example.com
  • Bio is optional — max 200 characters.
Personal Information
We'll never share your email.
Your Role (required)
Optional — max 200 characters.
Full WAI Checklist

Full WAI Checklist

Every requirement from the W3C WAI Forms Tutorial, mapped to code patterns.

  • Every input has a <label> linked via htmlFor/id
  • IDs generated with useId() — no hardcoded duplicates
  • Radio & checkbox groups wrapped in <fieldset>/<legend>
  • Related text fields grouped with role="group" + aria-labelledby
  • Selects use <optgroup> for grouped options
  • Overall instructions placed BEFORE the <form> element
  • Hints linked to inputs via aria-describedby
  • Required fields: aria-required + visual asterisk + sr-only text
  • Failed submit: error summary rendered with role="alert"
  • Failed submit: focus programmatically moved to error summary
  • Failed submit: first invalid field scrolled into view
  • Error summary links point to each invalid field
  • Each invalid field has aria-invalid + aria-describedby linking its error
  • Success state announced via role="status" + aria-live="polite"
  • Urgent errors use role="alert" + aria-live="assertive"
  • Custom controls have role, aria-checked/selected, and keyboard handlers
  • Errors shown with icon + text + color — never color alone
  • Focus indicators are visible (never outline: none)
  • Placeholder text is supplementary only, never the sole label