Live Regions are special ARIA zones that screen readers automatically read when content changes. They are the standard way to convey dynamic updates (form validation, search results, notifications) without requiring the user to move focus.
How it works step-by-step:
aria-live="polite" or aria-live="assertive".aria-live level, the screen reader queues or interrupts the current speech to read the new content.aria-atomic attribute controls whether the entire region is read or just the changed part.Complete implementation example:
1import { useState } from "react";23function StatusMessage({ message, type }: { message: string; type: "polite" | "assertive" }) {4 return (5 <div6 role="status"7 aria-live={type}8 aria-atomic="true"9 className="visually-hidden"10 >11 {message}12 </div>13 );14}1516// Real-world usage: a search form17function SearchForm() {18 const [results, setResults] = useState([]);19 const [status, setStatus] = useState("");20 const [isSearching, setIsSearching] = useState(false);2122 const handleSearch = async (query: string) => {23 if (!query) {24 setStatus("");25 setResults([]);26 return;27 }28 setIsSearching(true);29 setStatus("Searching...");30 try {31 const data = await search(query);32 setResults(data);33 setStatus(`Found ${data.length} results for "${query}"`);34 } catch {35 setStatus("Search failed. Please try again.");36 } finally {37 setIsSearching(false);38 }39 };4041 return (42 <div>43 <label htmlFor="search-input">Search</label>44 <input45 id="search-input"46 type="search"47 onChange={e => handleSearch(e.target.value)}48 aria-describedby="search-status"49 />50 <StatusMessage51 message={status}52 type="polite"53 />54 <ul aria-label="Search results">55 {results.map(r => (56 <li key={r.id}>{r.title}</li>57 ))}58 </ul>59 </div>60 );61}
Live region types:
aria-live="polite" — reads changes when the user is idle (low priority). Use for search results, status updates, non-urgent notifications.aria-live="assertive" — reads changes immediately, interrupting current speech. Use only for critical errors, urgent alerts, time-sensitive warnings.aria-atomic="true" — reads all content in the region, not just the changed portion.aria-atomic="false" (default) — reads only the changed text.aria-relevant="additions" — only announces when new content is added (ignores removals).CSS for visually hidden (accessible to screen readers):
1.visually-hidden {2 position: absolute;3 width: 1px;4 height: 1px;5 padding: 0;6 margin: -1px;7 overflow: hidden;8 clip: rect(0, 0, 0, 0);9 white-space: nowrap;10 border: 0;11}
Common mistakes:
aria-live="assertive" for everything — this interrupts the user mid-sentence and creates a terrible experience.<div> in and out, the live region may not fire.role="status" and aria-live on the same element without understanding the redundancy — role="status" implicitly sets aria-live="polite", so adding aria-live="polite" is redundant (but harmless).Performance considerations: