Molecules
Banner
One message with an intent, in one row, with an optional icon and actions.
Code
<div class="banner">
<span class="icon-box" aria-hidden="true"><svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Info"/></svg></span>
<div class="banner__body">
<p class="text">Your changes are saved automatically.</p>
</div>
<button type="button" class="button button--icon banner__action">
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Close"/></svg>
<span class="sr-only">Dismiss</span>
</button>
</div>
Why it exists
A page sometimes has to say something about itself: a problem, a change, something about to happen. A Banner says one such thing, in the flow of the page, where it can be read in context.
One message is the limit, and it keeps the Banner honest. Once something needs media, or a title, body and footer of controls, it is a Card.
An alert isn’t a component. What makes a message urgent is how it is announced, and that takes a live region already in the page, so urgency is a role on that region. One Banner serves every case, and a Banner Dock or a Toast only decides where it sits.
When to use
- For one message in the flow of a page: a warning above a Form, a notice in a Card.
- Not for a site announcement pinned to the page edge: that is a Banner Dock.
- Not for a passing confirmation in a corner: that is a Toast.
- Not for media, or a title, body and footer of controls: that is a Card.
- Not for a Field’s error: that is
.field__error.
Rules
- Intent is never colour alone. A Banner with a non-neutral intent starts with an icon, or states its intent in the text.
- Structure: icon,
.banner__body, then.banner__actionon one Button or on a.clusterof them. Actions can instead go in a.clusterat the end of the body, under the message. No other parts. - Roles: an in-flow Banner takes no role and no
aria-label. Putrole="status"(polite) orrole="alert"(urgent) on a region that is in the page before its message arrives, and insert the Banner into it. - Dismiss by setting
hidden; the Banner fades out (at once with reduced motion).
Keyboard and screen readers
A Banner is static, so the browser has nothing to do until a message arrives or someone dismisses one. Both are the product’s script.
- A live message is announced only if its region was in the page before the message arrived.
role="status"waits its turn, androle="alert"interrupts. - A Banner already in the page isn’t announced. It is read in order, like the rest of the content.
- Tab reaches the Buttons in it, in order.
- Dismissing hides the Button that has focus, so move focus somewhere sensible first.
An intent and a way to dismiss it
Code
<div class="banner banner--warning">
<span class="icon-box" aria-hidden="true"><svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Warning"/></svg></span>
<div class="banner__body">
<p class="text">Scheduled maintenance begins tonight at 22:00 UTC.</p>
</div>
<button type="button" class="button button--icon banner__action">
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Close"/></svg>
<span class="sr-only">Dismiss</span>
</button>
</div>
The icon carries the warning for anyone who can’t rely on the colour, and the Dismiss Button keeps a hidden label.
A title and more than one action
Code
<div class="banner banner--accent">
<span class="icon-box" aria-hidden="true"><svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Info"/></svg></span>
<div class="banner__body">
<p class="text font-bold">Design system v2.4 is available</p>
<p class="small-text">Updated tokens and native anchor positioning.</p>
<div class="cluster mt-sm">
<button type="button" class="button"><span>Later</span></button>
<button type="button" class="button button--strong button--accent"><span>Update</span></button>
</div>
</div>
</div>
A title is .text.font-bold, because the Banner sets no type. Mark the main Button --strong --accent only if it needs the weight.
Several actions in the body sit under the message, where they can wrap and the message keeps its width on a small screen. At the side, with .banner__action, suits one action, a dismiss Button, or a short message with a pair of icon Buttons.
A Live Message
Code
<!-- In the page from the start -->
<div role="status" aria-label="Upload status" id="upload-status"></div>
<!-- Inserted when the upload finishes -->
<div class="banner banner--success">
<span class="icon-box" aria-hidden="true"><svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#Check"/></svg></span>
<div class="banner__body"><p class="text">Upload complete.</p></div>
</div>
Both parts are shown here at once. In use, the script inserts the Banner into the region.
Do and Don’t
| Do | Don’t |
|---|---|
| Put several actions in the body when the Banner can reach a small screen. | Line several text Buttons up at the side, where they squeeze the message. |
| Start a non-neutral Banner with an icon, or state the intent in the text. | Leave colour to carry the intent. |
| Put the message in a text atom. | Expect the Banner to set type. |
Put role="status" or role="alert" on a region already in the page. | Put a role or aria-label on an in-flow Banner. |
Dismiss by setting hidden. | Remove it with a dismissing class. |
| Use a Card for media, or a title, body and footer of controls. | Add other parts to a Banner. |
In Storybook
See also
- Banner Dock: Pins a Banner to the edge of the page, for site announcements, maintenance notices and consent bars.
- Toast: A short message that appears in a corner of the screen, built from a Banner in a live stack.
- Card: A surface with named parts, such as a header, a body and a footer, for one thing a person can read, compare or act on.
- Icon and Icon Box: A small glyph that helps people recognise something, on its own or in a frame.