Live regions

Toast notifications

There is no APG pattern for this, which is part of why it is the one people get wrong most often.

What to check. With VoiceOver on, trigger a polite toast while it is reading something else — it should wait its turn. Trigger the error and it should interrupt. Press "Same message twice": both are announced, even though the text is identical. Hover a toast and it stops counting down.

The five failures

  1. Announcing by inserting the live region itself. Creating a <div role="alert"> and putting text in it in the same task usually announces nothing — assistive technology reacts to mutations inside a region it is already observing. Both regions here are created empty at page load.
  2. Making the visible stack the live region. The stack mutates constantly: enter animations, dismiss buttons, timers removing nodes. Worse, role="alert" implies aria-atomic="true", so a second toast re-announces the first one too. Here the stack is a plain labelled landmark, and announcements are mirrored into separate single-message regions.
  3. assertive for everything. It interrupts the user mid-sentence — including mid-sentence in the thing they were reading to decide what to do. Only errors use it.
  4. Auto-dismiss that cannot be paused (WCAG 2.2.1) or that is too short to read. Timers pause on hover and on focus, resume with only the time that was left, and errors never expire.
  5. Focus vanishing. If a toast is removed while the user is tabbed into it, focus falls back to <body> and the screen reader jumps to the top of the page. Focus is moved deliberately before the node is removed.
Keyboard interaction
TabReach the toast's action and dismiss buttons. Focusing anything in the stack pauses every timer.
Enter or SpaceActivate the focused action or dismiss button.

The stack is a labelled region landmark, so a screen reader user can jump to it with the rotor and review notifications at their own pace rather than chasing them before they expire.