Accessibility pattern · Disclosure and content

Callout

Each callout starts with a word, Note, Tip, Warning, Success or Danger, so its meaning never rests on its color or its icon. They are static text, so nothing is announced on load; the one that can be dismissed hands focus to the next callout when it goes.

WCAG criteria
7
Keyboard rules
2
Checked with
axe, keyboard and the inspector

Live demo

Try it

Use it with a mouse, a keyboard or a screen reader. The inspector beside it shows what the browser tells assistive technology as you go: focus, state changes and announcements.

Connect your own domain

Point your domain at your store in a few minutes. Read these before you change any settings.

The demo works without JavaScript only as far as its HTML does; the inspector needs JavaScript.

Keyboard

Keys it answers to

Every action works without a pointer.

KeyWhat it does
TabReaches the tip's dismiss button; the callouts themselves are text and take no tab stop.
Enter or SpaceDismisses the tip and moves focus to the callout that takes its place.

Screen readers

What it announces

Written from the roles, names and states in the markup.

WhenExpected announcement
Reading reaches a calloutWarning: Changing nameservers moves your email too. Copy your mail records across…
Focus reaches the dismiss buttonDismiss tip, button
The tip is dismissedWarning: Changing nameservers moves your email too… (focus is on the next callout), then Tip dismissed
The page loadsNothing: static callouts are read in order, never announced

These are expected announcements, not recordings. Wording and order differ between screen readers and browsers.

Code

Copy the code

The exact files this demo runs on. The styles are served with a prefix that keeps this site's own styles out of the demo; what you copy is the original.

The markup

<div class="ap-callout" data-ap-callout>
  <h3 class="ap-callout__intro">Connect your own domain</h3>
  <p class="ap-callout__lead">Point your domain at your store in a few minutes. Read these before you change any settings.</p>

  <div class="ap-callout__stack">
    <aside class="ap-callout__item ap-callout__item--note" role="note">
      <svg class="ap-callout__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="M12 11v5"/><path d="M12 7.5h.01"/></svg>
      <div class="ap-callout__body">
        <p class="ap-callout__label">Note:</p>
        <p class="ap-callout__text">DNS changes can take up to 48 hours to reach every network. Until then, some visitors may still reach your old site.</p>
      </div>
    </aside>

    <aside class="ap-callout__item ap-callout__item--tip" role="note">
      <svg class="ap-callout__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M9 18h6"/><path d="M10 21h4"/><path d="M12 3a6 6 0 0 0-3.6 10.8c.7.5 1.1 1.3 1.1 2.2h5c0-.9.4-1.7 1.1-2.2A6 6 0 0 0 12 3Z"/></svg>
      <div class="ap-callout__body">
        <p class="ap-callout__label">Tip:</p>
        <p class="ap-callout__text">Add both the www and the bare version of your domain. We send one to the other, so people reach your store whichever they type.</p>
      </div>
      <button type="button" class="ap-callout__dismiss" aria-label="Dismiss tip" data-ap-dismiss>
        <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M6 6l12 12M18 6 6 18"/></svg>
      </button>
    </aside>

    <aside class="ap-callout__item ap-callout__item--warning" role="note">
      <svg class="ap-callout__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
      <div class="ap-callout__body">
        <p class="ap-callout__label">Warning:</p>
        <p class="ap-callout__text">Changing nameservers moves your email too. Copy your mail records across before you switch, or messages will stop arriving.</p>
      </div>
    </aside>

    <aside class="ap-callout__item ap-callout__item--success" role="note">
      <svg class="ap-callout__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="9"/><path d="m8 12.5 2.7 2.7L16.2 9.6"/></svg>
      <div class="ap-callout__body">
        <p class="ap-callout__label">Success:</p>
        <p class="ap-callout__text">When the status reads Active, your domain is live and its security certificate is in place.</p>
      </div>
    </aside>

    <aside class="ap-callout__item ap-callout__item--danger" role="note">
      <svg class="ap-callout__icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M7.9 2.5h8.2l5.4 5.4v8.2l-5.4 5.4H7.9l-5.4-5.4V7.9Z"/><path d="m15 9-6 6M9 9l6 6"/></svg>
      <div class="ap-callout__body">
        <p class="ap-callout__label">Danger:</p>
        <p class="ap-callout__text">Removing a domain takes your store offline at that address straight away. It cannot be undone.</p>
      </div>
    </aside>
  </div>

  <p class="ap-callout__sr" role="status"></p>
</div>

WCAG 2.2

What it meets

The success criteria this pattern takes care of, and how.

  • 1.3.1 Info and Relationships Level A

    Each callout is an aside exposed as a note, and its kind is a word in the text, so the structure does not depend on how it looks.

  • 1.4.1 Use of Color Level A

    Note, Tip, Warning, Success and Danger are written out and drawn with different icons; the tint and stripe only repeat what the word says.

  • 1.4.3 Contrast (Minimum) Level AA

    The label and body text clear 4.5:1 on every tinted background, in the light and the dark theme.

  • 2.4.3 Focus Order Level A

    When the tip is dismissed, focus moves to the callout that takes its place instead of falling back to the top of the page.

  • 2.5.8 Target Size (Minimum) Level AA

    The dismiss button is 32 by 32 pixels, above the 24-pixel minimum, with space around it.

  • 4.1.2 Name, Role, Value Level A

    The dismiss button's icon is hidden and the button is named Dismiss tip, so it says what it closes.

  • 4.1.3 Status Messages Level AA

    Tip dismissed is also confirmed in a polite status message, so the change is heard even where focusing a callout reads nothing.

Usage

When to use it

Use it

  • Information that sits beside the main text: a caveat, a shortcut, a risk, or a sign that a step worked.
  • Docs, help pages and settings where one sentence must not be missed by people who skim.

Use something else

  • Messages caused by something the person just did: use a status message or an alert banner, which are announced.
  • Whole sections of content: a callout every paragraph is noise, and readers start skipping all of them.
  • Errors in a form: tie them to the field they belong to with the form errors pattern.

Common failures

How it usually goes wrong

  • role=alert on static content

    An alert is announced the moment it appears, so callouts marked that way all shout at once when the page loads, and none of them is news.

  • Meaning carried by color alone

    A yellow box and a red box look the same to many people with color vision deficiencies and to every screen reader. A word at the start says which it is.

  • An icon with no text

    A triangle is not a label. The icon here is decoration, hidden from assistive technology, and the visible word does the work.

  • Five landmarks in a row

    An aside directly in the main content becomes a complementary landmark, so a stack of them floods the landmarks list. role=note keeps the meaning without the noise.

  • Focus lost on dismiss

    Removing the element that has focus drops keyboard users at the top of the page. Focus moves to the next callout instead.

  • Tinted text that fails contrast

    Colored body text on a tinted background often lands near 3:1. Only the short label takes the tone color here; the sentence stays in the main text color.

Notes

Building it

  • The label is real text, not CSS content, so it is read, translated and copied with the rest of the sentence.
  • Give the callout that can be dismissed a name in its button (Dismiss tip, not Close), and remember the choice for next time, in storage or the account, so it stays gone.
  • The next callout gets tabindex=-1 only so the script can focus it; it never joins the Tab order.
  • Use a callout for content written into the page. For a message the page reacts with, use a role=status region, which is announced, or role=alert if it is urgent.

Sources: WAI-ARIA 1.2: the note role · ARIA in HTML: the aside element · Understanding SC 1.4.1: Use of Color

Checked with axe in light and dark themes, at desktop and phone widths, and by keyboard. Not yet tested with every screen reader and browser pair. Report a correction