When a form validation error appears as inline red text, or a toast notification slides in from the corner, screen reader users receive no indication that anything has changed — their focus is still on the input field or wherever it was when they triggered the action. This is a silent failure from the assistive technology's perspective. WCAG 2.2 SC 4.1.3 (Status Messages) requires that status messages be programmatically determinable by assistive technology without receiving focus. SC 1.3.1 (Info and Relationships) covers the relationship between an error message and its field. Section 508 2018 Refresh 502.3.14 requires that changes in status be programmatically determinable. The practical consequence: screen reader users submit forms with errors and receive no feedback, cycling through submission repeatedly with no understanding of why the form fails.
Medium because the failure silences important feedback for screen reader users without completely blocking form access for sighted users.
Wrap dynamic content — form errors, success toasts, loading states, live counters — in an aria-live region. Place the container in the DOM before content appears; adding aria-live after the fact does not work reliably.
// Error summary that receives focus on submission failure
{hasErrors && (
<div
id="error-summary"
role="alert"
aria-live="assertive"
tabIndex={-1}
ref={errorSummaryRef}
>
<h2>Please fix the following errors:</h2>
<ul>
{errors.map(e => <li key={e.field}>{e.message}</li>)}
</ul>
</div>
)}
// Polite announcements for non-urgent updates
<div aria-live="polite" aria-atomic="true">
{statusMessage}
</div>
// Associate field-level errors with inputs
<input
id="email"
type="email"
aria-invalid={!!errors.email}
aria-describedby={errors.email ? "email-error" : undefined}
/>
{errors.email && (
<p id="email-error" role="alert">{errors.email}</p>
)}
Use aria-live="assertive" only for urgent errors that interrupt the user. Use aria-live="polite" for status updates that can wait for a natural pause.
ID: accessibility-basics.semantic-structure-aria.aria-live-regions
Severity: medium
What to look for: Enumerate every relevant item. Look for forms with validation feedback, notifications, alerts, and real-time data updates. Check whether these use aria-live, aria-atomic, and aria-relevant attributes to announce changes to screen reader users. Without aria-live, screen reader users won't know content has changed.
Pass criteria: At least 1 of the following conditions is met. Dynamic content updates (form validation errors, notifications, alerts, real-time data) are announced via aria-live regions. Updates include appropriate aria-atomic and aria-relevant attributes.
Fail criteria: Validation errors, notifications, or dynamic updates appear visually but are not announced via aria-live regions.
Skip (N/A) when: The application has no dynamic content updates or form validation.
Detail on fail: Identify which dynamic updates lack aria-live. Example: "Form validation errors appear inline but are not announced to screen readers. Success notification toast has no aria-live region."
Remediation: Use aria-live regions for dynamic content:
<div aria-live="polite" aria-atomic="true">
{errorMessage && <p role="alert">{errorMessage}</p>}
</div>
{/* For form validation errors */}
<div aria-live="assertive" role="alert">
{validationErrors.map(err => <p key={err.field}>{err.message}</p>)}
</div>