Toast Notifications / Snackbars
Transient status and error messages with separate live text, persistent actions, user-controlled dismissal, and tested timing behavior
Overview
Toast notifications are brief messages that confirm an action or report status. They become inaccessible when updates have no programmatic status, disappear before users can perceive them, or place controls inside a status or alert. A broadly compatible technique is to keep an empty live-message node rendered and update its text. This is interoperability advice, not a categorical WCAG rule.
Relevant criteria:
- 4.1.3 Status Messages applies when content provides qualifying status information without receiving focus.
- 2.2.1 Timing Adjustable applies when timing limits an activity, subject to its conditions and exceptions.
- 2.2.2 Pause, Stop, Hide can apply to auto-updating information.
Keep live-message nodes text-only. Put Retry, Undo, and Dismiss controls in ordinary focusable UI outside the live region. Important actions should also remain available elsewhere; use managed focus or a dialog when immediate action is required.
Status Toast
Silent Visual Toast vs. Separate Status and Controls
View inaccessible code
<button onclick="toast.hidden = false">Save</button>
<div id="toast" hidden>Saved!</div>View accessible code
<!-- Rendered message node contains text only. -->
<span id="save-status" role="status" class="visually-hidden"></span>
<button onclick="showSaveResult()">Save</button>
<div id="visible-toast" hidden>
<span aria-hidden="true">Saved successfully</span>
<button aria-label="Dismiss notification">×</button>
</div>
<script>
function showSaveResult() {
saveStatus.textContent = 'Saved successfully'
visibleToast.hidden = false
}
</script>| Version | Expected programmatic result |
|---|---|
| Silent visual toast | No status semantics expose the new message. |
| Separate status and controls | The concise result is exposed as a polite status, while Dismiss remains an ordinary button. Exact speech depends on the tested AT/browser pair. |
Error Toast with an Action
Controls Inside Alerts vs. Separate Message and Action UI
View inaccessible code
<!-- Focusable controls are descendants of the alert. -->
<div role="alert">
Failed to save <button>Retry</button><button>Dismiss</button>
</div>View accessible code
<!-- Concise live text. -->
<span id="save-error" role="alert" class="visually-hidden"></span>
<!-- Ordinary focusable UI outside the live region. -->
<div id="visible-error-toast" hidden>
<span aria-hidden="true">Failed to save</span>
<button>Retry</button>
<button aria-label="Dismiss notification">×</button>
</div>
<button>Persistent Save action</button>| Pattern | Expected behavior |
|---|---|
Controls inside alert | The urgent message and interactive descendants are conflated; discovery and focus behavior are unreliable. |
| Separate message and action UI | Urgent text is exposed as an alert; Retry and Dismiss remain ordinary focusable controls, and Save remains available persistently. |
Timing and evidence
Do not classify every auto-dismiss toast as a 2.2.1 failure. Evaluate the complete activity, message purpose, duration, exceptions, and whether the information or action remains available. Test status and alert updates with named AT/browser/OS/version combinations and record the date; do not publish a universal exact announcement string.