Accessible Form Patterns

Examples demonstrating proper ARIA attributes, help text connections, and accessible validation patterns.

1. Help Text with aria-describedby

Use aria-describedby to connect help text to inputs. Screen readers announce help text when the input receives focus.

Must be 8+ characters with one uppercase letter and one number.
3-20 characters, letters and numbers only.

2. Multiple Descriptions

Space-separate multiple IDs in aria-describedby. Screen readers announce them in order.

Format: MM/DD/YYYY
Used only for age verification. Never shared.

3. Help Text + Validation Feedback

When validation fails, reference both help text and error message in aria-describedby. Add aria-invalid="true" to indicate the invalid state.

We'll never share your email.
Looks good!
We'll never share your email.
Please enter a valid email address (e.g., user@example.com).

4. Required Fields with Visual + ARIA Indicators

Use both required and aria-required="true". Add a visual indicator (asterisk) for sighted users.

* Required fields

Format: (555) 123-4567

5. Grouped Controls with Fieldset/Legend

Use <fieldset> and <legend> to group related controls. Screen readers announce the legend with each control.

Notification Preferences
Contact Method

6. Accessible Switches

Add role="switch" to switch controls so screen readers announce them as switches rather than checkboxes.

Reduces eye strain in low-light environments.

7. Visually Hidden Labels

When hiding labels visually, use .visually-hidden (not display: none) so screen readers still announce them.

8. Live Error Announcements

Use aria-live regions to announce validation errors to screen readers when the form is submitted.

Please enter a valid email address.
Password must be at least 8 characters.

9. Focus Management on Error

On validation error, move focus to the first invalid field. This helps keyboard and screen reader users find errors quickly.

Please enter your first name.
Please enter your last name.
Please enter a valid email.
Try submitting with empty fields