Single-page applications update content dynamically—cart counts change, search results replace prior results, toast notifications appear, status messages resolve—all without a page reload. Screen readers only announce DOM changes inside aria-live regions; DOM changes elsewhere are silent. WCAG 2.2 SC 4.1.3 (Level AA) requires status messages to be programmatically determinable without receiving focus, and SC 1.3.1 (Level A) requires that information conveyed through presentation be available to AT. Section 508 2018 Refresh 502.3.14 requires applications to notify AT of relevant UI events. A cart update, form submission success, or real-time filter that silently changes the DOM shuts screen reader users out of the live application state.
Medium because missing `aria-live` regions cause screen reader users to miss status messages and dynamic content changes, degrading usability of dynamic interactions without preventing access to static content.
Wrap every dynamic status message in an aria-live region. For non-urgent updates (cart count, filter results), use aria-live="polite". For urgent alerts (errors, session warnings), use aria-live="assertive":
// In a shared Announcer component — mount once at root
const [politeMessage, setPoliteMessage] = useState('');
export function useAnnounce() {
return (msg: string) => {
setPoliteMessage(''); // Clear first to re-trigger announcement
requestAnimationFrame(() => setPoliteMessage(msg));
};
}
<div
aria-live="polite"
aria-atomic="true"
className="sr-only"
>
{politeMessage}
</div>
In your cart or filter component:
const announce = useAnnounce();
const addToCart = (item: Item) => {
addItem(item);
announce(`${item.name} added to cart. ${cartCount + 1} items total.`);
};
Avoid aria-live="assertive" for routine updates—it interrupts whatever the screen reader is currently reading.
gov-section-508.forms-interactive.aria-livemediumaria-live regions with appropriate politeness levels (polite, assertive, or implied off).aria-live="polite" or aria-live="assertive" as appropriate. Updates are clear and timely.aria-live, causing screen reader users to miss important announcements."When a user adds a product to the cart, the page updates the cart count and shows a toast notification visually. No aria-live region announces this to screen reader users. Search results update dynamically when filters are changed, but changes are not announced."aria-live:
const [message, setMessage] = useState('');
const addToCart = () => {
// Add product
setMessage('Product added to cart');
setTimeout(() => setMessage(''), 5000);
};
return (
<>
<button onClick={addToCart}>Add to Cart</button>
<div aria-live="polite" aria-atomic="true" className="sr-only">
{message}
</div>
</>
);