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.
Labeling Controls
A visible label linked with htmlFor gives every input an accessible name. Placeholders are never a substitute.
✓ Correct
✗ No label
Grouping Controls
Radios, checkboxes, and related fields need semantic grouping so screen readers announce the group name alongside each control.
Radio buttons → <fieldset> + <legend>
Checkboxes — also need <fieldset> + <legend>
Select with <optgroup>
Related text fields → role="group" + aria-labelledby
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
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.
- Fields marked with an asterisk are required.
- Email must be a valid address, e.g.
you@example.com - Bio is optional — max 200 characters.
Full ARIA Checklist
Every rule from this tutorial, mapped to the pattern it covers.
- 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