HTML Formatterhtmlformatteronline.com

Alerts and toasts

Four inline alert types plus a stacking toast system with correct live regions.

cssalerttoastnotificationbanneraria-live
<div class="alerts">
  <div class="alert info">
    <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg>
    <div><strong>Scheduled maintenance</strong>
      <p>The API will be read-only on Sunday between 02:00 and 04:00 UTC.</p></div>
  </div>

  <div class="alert ok" role="status">
    <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M8.5 12.5l2.5 2.5 4.5-5"/></svg>
    <div><strong>Project deployed</strong>
      <p>Live at <a href="#">acme.example.com</a> — took 38 seconds.</p></div>
  </div>

  <div class="alert warn">
    <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 4l9 16H3z"/><path d="M12 10v4M12 17h.01"/></svg>
    <div><strong>Your card expires next month</strong>
      <p><a href="#">Update your payment details</a> to avoid an interruption.</p></div>
    <button class="close" type="button" aria-label="Dismiss this notice">&times;</button>
  </div>

  <div class="alert bad" role="alert">
    <svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M15 9l-6 6M9 9l6 6"/></svg>
    <div><strong>Build failed</strong>
      <p>Module not found: <code>./utils/format</code> at line 12 of <code>app.js</code>.</p></div>
  </div>
</div>

<div class="try">
  <button class="btn" type="button" data-toast="ok">Show a success toast</button>
  <button class="btn ghost" type="button" data-toast="bad">Show an error toast</button>
</div>

<!-- toasts land here; the region exists from page load so it is watched -->
<div class="toasts" id="toasts" role="region" aria-label="Notifications"></div>

How it works

role="status" versus role="alert". This is the whole accessibility story for notifications and it gets skipped constantly. status is polite: the screen reader finishes its current sentence and then announces. alert interrupts immediately. Use alert only for errors and things that need action now; use status for confirmations. An alert on every "Saved" message makes a screen reader unusable.

The toast container exists from page load. A live region has to be in the DOM before content is inserted into it — if you create the container and its message in the same tick, many screen readers announce nothing at all. That is the most common toast bug there is, and it is invisible unless you test with a screen reader.

Errors do not auto-dismiss. A four-second timeout on a message someone needs to act on is hostile: people reading slowly, using magnification, or simply looking elsewhere will miss it. Confirmations expire; errors wait.

pointer-events: none on the stack, auto on the toasts. Without this, the invisible container sits over the bottom-right corner of your page and eats clicks on anything underneath.

Custom properties drive the four variants. Three variables per variant — tint, border, ink — and the icon picks up the ink colour through stroke: var(--ink).

Accessibility notes

Icons are aria-hidden because each alert has a heading that says the same thing in words. A red triangle alone means nothing to a screen reader.

The dismiss buttons have descriptive labels rather than reading out "times" or "x".

Colour is never the only signal: each variant has an icon, a bold heading and a coloured left border, so the four types are distinguishable in greyscale.

Test toasts with a screen reader before shipping them. Announcements that work in one browser and silently fail in another are the norm in this component, and the timing of when the region enters the DOM is usually the cause.

Making it yours

Toasts belong bottom-right on desktop and full-width at the bottom on mobile, which is what the 480-pixel rule does. Top-centre is also defensible; top-right collides with browser download prompts and extension popups.

Cap the stack at three or four. Beyond that, older messages should be replaced rather than queued — a wall of toasts is noise.

For an inline alert that must not be missed, put it above the content it concerns and move focus to it. A dismissable banner at the top of the page is for information; an alert next to a failing field is for action.

Related templates

Check your version

Once you have edited this, the HTML validator will catch any tag you left unclosed, and the formatter will tidy the indentation. Both run in your browser.