Back to DocsRecipe
Accessible form validation
Real-time inline validation with screen-reader announcements, error summaries, and focus management — no ARIA left behind.
Pattern overview
aria-describedbylinks each input to its live-region error container.role="alert"on the error summary ensures AT announces it immediately.- Focus is sent to the first invalid field on submit, then to the summary on correction.
- Error messages use
aria-live="polite"for inline updates without interrupting the user.
Code skeleton
<form noValidate onSubmit={handleSubmit}>
<div role="alert" tabIndex={-1} ref={summaryRef}>
{errors.length} error{errors.length !== 1 && "s"}
</div>
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
aria-describedby="email-err"
aria-invalid={!!emailError}
ref={emailRef}
/>
<span id="email-err" role="status" aria-live="polite">
{emailError}
</span>
<button type="submit">Subscribe</button>
</form>Key takeaways
- Always pair client-side validation with server-side checks — never trust the browser alone.
- Use live regions sparingly; only the changed error text should update, not the entire form.
- Test with VoiceOver, NVDA, and keyboard-only navigation before shipping.