aria-live tells screen readers to watch a region of the page and announce any text changes automatically — even when focus has not moved to that region.
Single-page apps, search-as-you-type, form validation, notifications, countdown timers, shopping cart updates — modern web UIs change content dynamically without full page loads. Sighted users see these changes visually. Screen reader users miss them entirely unless you use aria-live.
| Value | Behavior | When to Use |
|---|---|---|
aria-live="polite" |
Announces after the user finishes what they're currently doing | Search results, status updates, non-urgent notifications |
aria-live="assertive" |
Interrupts the screen reader immediately | Critical errors, time-sensitive alerts, destructive action confirmations |
aria-live="off" |
No announcements (default) | Regions you don't want announced |
Use assertive sparingly. Interrupting a screen reader mid-sentence is highly disruptive. Most use cases are polite.
See how 321 websites scored →
View the 2026 ReportThese roles are equivalent to live regions with preset behavior:
<!-- role="status" = aria-live="polite" + aria-atomic="true" --> <div role="status">Your preferences have been saved.</div> <!-- role="alert" = aria-live="assertive" + aria-atomic="true" --> <div role="alert">Error: Payment failed. Please try again.</div>
The most important rule: declare the live region in the DOM before you put content in it. Screen readers register live regions when the page loads. If you inject the aria-live container and the content at the same time, many screen readers miss the announcement.
<!-- In your HTML on page load (empty) -->
<div id="status-region" role="status" aria-live="polite" aria-atomic="true"></div>
<script>
// Later — update the region's content
document.getElementById('status-region').textContent = '12 results found';
</script>
<!-- HTML (on page load, empty) -->
<p role="status" aria-live="polite" id="search-count"></p>
<script>
// After search results render
document.getElementById('search-count').textContent =
`${results.length} results for "${query}"`;
</script>
<!-- Empty container in HTML -->
<div role="status" id="form-feedback"></div>
<script>
async function submitForm(e) {
e.preventDefault();
await saveData();
const feedback = document.getElementById('form-feedback');
feedback.textContent = 'Your profile has been updated successfully.';
}
</script>
<div role="alert" id="error-region"></div>
<script>
function showErrors(errors) {
document.getElementById('error-region').innerHTML =
`<p>Please fix ${errors.length} error(s):</p>
<ul>${errors.map(e => `<li>${e}</li>`).join('')}</ul>`;
}
</script>
<span role="status" id="cart-status" class="sr-only"></span>
<script>
function addToCart(product) {
cart.add(product);
document.getElementById('cart-status').textContent =
`${product.name} added to cart. Cart now has ${cart.count} items.`;
}
</script>
aria-atomic="true" (default on role="status"/role="alert") means the entire region is announced when any part changes — not just the changed portion. Use this for most cases.
aria-relevant lets you specify which changes trigger announcements: "additions", "removals", "text", or "all". The default is "additions text". Rarely needed.
WCAG 2.1 criterion 4.1.3 (Level AA) requires that status messages — "Form saved", "3 errors found", "Item added to cart" — be programmatically determinable without receiving focus. This is exactly what aria-live and role="status"/role="alert" provide.
Accessalyze finds missing live regions and status message violations as part of its WCAG 2.1 audit.
Run Free Accessibility Audit →See real website accessibility scores: Browse 244+ free accessibility audits →
Try it yourself
Enter your website URL to get a free accessibility score.