Accessibility Certified – Home

Status messages that get through without stealing focus

“Added to basket”, “Saved”, “3 results”: people see such messages, but a screen reader only announces them if they sit in a live region.

4.1.32.2.12.4.111.3.1

Live demo

This demo is checked with axe-core without violations and fully operable by keyboard.

Try it with the keyboard: Tab, Enter, Space, the arrow keys and Escape. With a screen reader on, you hear what gets announced.

The live demo needs JavaScript. Code and requirements are below.

Keyboard interaction

Tab
Focus stays on the button you pressed; the message is still announced.
Enter / Space
Triggers the action or dismisses the message (close button).

When to use this pattern

4.1.3 Status Messages requires status messages to be programmatically determinable so that assistive technology can present them without moving focus. Typical cases: confirmation after saving, the number of results after filtering, a note that something was added to the basket.

Toasts that vanish after a few seconds are risky: people who read slowly or work zoomed in miss them. Keep important messages until someone closes them, or repeat the information in a fixed place.

Roles, states and properties

  • The container with role="status" (equivalent to aria-live="polite") is present and empty when the page loads; text is written into it later.
  • role="alert" (equivalent to aria-live="assertive") only for urgent messages such as errors that matter right now.
  • The message is short and makes sense on its own.
  • No focus change to the message; focus stays where the person is working.
  • The toast does not cover focused elements (2.4.11 Focus Not Obscured (Minimum)) and can be dismissed.

Keyboard interaction

KeyEffect
TabFocus stays on the button you pressed; the message is still announced.
Enter / SpaceTriggers the action or dismisses the message (close button).

Code

HTML and JavaScript (shortened)
<!-- present on load, empty -->
<div role="status" class="toast-region"></div>

<button type="button" id="save">Save</button>

<script type="module">
const region = document.querySelector('.toast-region');
document.getElementById('save')
  .addEventListener('click', () => {
    region.textContent = 'Changes saved.';
  });
</script>

Common mistakes

  • The live region is inserted into the DOM together with the message, so many screen readers say nothing.
  • Everything is role="alert", so every small thing interrupts whatever is being read.
  • Focus jumps to the message and the person loses their place in the form.
  • The toast disappears after two seconds and was the only place with that information.

Related WCAG criteria

Sources

Are your components built like this?

The free check finds many issues automatically. In the audit a person tests every component with a keyboard and a screen reader.

Free checkSee our method