Banner
A banner is a page- or app-level announcement strip: a single full-bleed horizontal row (leading icon + message + optional inline action + dismiss) that spans its container edge-to-edge with no rounded card border, optionally pinned to the top. Use it for cookie notices, maintenance windows, promos, and system status.
It is distinct from alert — alert is a rounded,
inset, always-subtle inline status card; banner is a borderless full-bleed
band and adds a data-emphasis="solid" fill that alert never has. Put it in
a full-width slot (outside a centered max-width wrapper) to reach the edges.
Variants
Section titled “Variants”The status tone is data-tone: info (default), success, warning,
danger.
<div style="display: flex; flex-direction: column; gap: var(--re-space-3)">
<aside class="re-banner" role="region" aria-label="Announcement">
<span class="re-banner__icon" aria-hidden="true">i</span>
<p class="re-banner__message">
We use cookies to improve your experience.
<a class="re-banner__action" href="#privacy">Learn more</a>
</p>
</aside>
<aside class="re-banner" data-tone="success" role="region" aria-label="Status">
<span class="re-banner__icon" aria-hidden="true">✓</span>
<p class="re-banner__message">All systems operational.</p>
</aside>
<aside class="re-banner" data-tone="warning" role="region" aria-label="Notice">
<span class="re-banner__icon" aria-hidden="true">!</span>
<p class="re-banner__message">
Your trial ends in 3 days.
<a class="re-banner__action" href="#billing">Upgrade now</a>
</p>
</aside>
<aside class="re-banner" data-tone="danger" role="region" aria-label="System status">
<span class="re-banner__icon" aria-hidden="true">!</span>
<p class="re-banner__message">
Scheduled maintenance tonight 02:00–03:00 UTC.
<a class="re-banner__action" href="#status">View status</a>
</p>
</aside>
</div> Solid emphasis
Section titled “Solid emphasis”data-emphasis="solid" swaps the tint for a bold fill — the *-700 status
scale with white text, which clears WCAG AA contrast. Reserve it for genuinely
high-priority strips.
<div style="display: flex; flex-direction: column; gap: var(--re-space-3)">
<aside class="re-banner" data-emphasis="solid" role="region" aria-label="Promo">
<span class="re-banner__icon" aria-hidden="true">★</span>
<p class="re-banner__message">
Black Friday: 40% off all plans this week.
<a class="re-banner__action" href="#pricing">See plans</a>
</p>
</aside>
<aside
class="re-banner"
data-tone="success"
data-emphasis="solid"
role="region"
aria-label="Status"
>
<span class="re-banner__icon" aria-hidden="true">✓</span>
<p class="re-banner__message">Payment received — your account is now active.</p>
</aside>
<aside
class="re-banner"
data-tone="warning"
data-emphasis="solid"
role="region"
aria-label="Notice"
>
<span class="re-banner__icon" aria-hidden="true">!</span>
<p class="re-banner__message">
Action required: confirm your email address.
<a class="re-banner__action" href="#verify">Confirm</a>
</p>
</aside>
<aside
class="re-banner"
data-tone="danger"
data-emphasis="solid"
role="region"
aria-label="Incident"
>
<span class="re-banner__icon" aria-hidden="true">!</span>
<p class="re-banner__message">
We are investigating an active service disruption.
<a class="re-banner__action" href="#status">Live updates</a>
</p>
</aside>
</div> Dismissible
Section titled “Dismissible”Mark the host [data-re-dismissible], add a [data-re-dismiss] button, and call
enhanceDismissible() (the same behavior alert
and toast use).
<aside
class="re-banner"
data-tone="warning"
role="region"
aria-label="Announcement"
data-re-dismissible
id="dismissible-banner"
>
<span class="re-banner__icon" aria-hidden="true">!</span>
<p class="re-banner__message">
This banner can be dismissed.
<a class="re-banner__action" href="#privacy">Learn more</a>
</p>
<button type="button" class="re-banner__dismiss" data-re-dismiss aria-label="Dismiss">
×
</button>
</aside> Centered
Section titled “Centered”data-align="center" caps the message at a readable measure and centers it while
the fill stays full-bleed — the classic announcement-bar look.
<aside
class="re-banner"
data-emphasis="solid"
data-align="center"
role="region"
aria-label="Promo"
>
<p class="re-banner__message">
Free shipping on every order this weekend.
<a class="re-banner__action" href="#shop">Shop now</a>
</p>
</aside> Sticky
Section titled “Sticky”data-sticky pins the banner to the top of its scroll container while content
scrolls underneath. Under a fixed site header, override --re-banner-sticky-top.
Scroll this region — the banner stays pinned to the top.
More content below to enable scrolling.
Even more content.
Keep scrolling.
Almost there.
<div
style="
block-size: 9rem;
overflow: auto;
border: var(--re-border-default);
border-radius: var(--re-radius-md);
"
>
<aside
class="re-banner"
data-tone="danger"
data-emphasis="solid"
data-sticky
role="region"
aria-label="System status"
data-re-dismissible
>
<span class="re-banner__icon" aria-hidden="true">!</span>
<p class="re-banner__message">
Scheduled maintenance tonight 02:00–03:00 UTC.
<a class="re-banner__action" href="#status">View status</a>
</p>
<button type="button" class="re-banner__dismiss" data-re-dismiss aria-label="Dismiss">
×
</button>
</aside>
<div style="padding: var(--re-space-4); display: grid; gap: var(--re-space-3)">
<p>Scroll this region — the banner stays pinned to the top.</p>
<p>More content below to enable scrolling.</p>
<p>Even more content.</p>
<p>Keep scrolling.</p>
<p>Almost there.</p>
</div>
</div> - Sticky:
data-stickypins the banner to the top of its scroll container. Under a fixed site header, override--re-banner-sticky-topin one line. - Persistence:
enhanceDismissibleonly sets[hidden]for the session. A cookie notice that must stay dismissed across reloads needs your app to persist that choice (e.g.localStorage) and conditionally render — by design, the library adds no new JavaScript here. - Full-bleed is plain
inline-size: 100%(nocalc(50% - 50vw)hack): the band fills whatever slot you place it in.
Accessibility
Section titled “Accessibility”- Keyboard — the banner itself is not focusable; the only interactive parts
are native. The inline
.re-banner__actionlink is a real<a href>(Tab to focus, Enter to follow). The[data-re-dismiss]close button is a native<button>, so Enter and Space activate it —enhanceDismissiblealso handles Enter/Space itself and hides the closest[data-re-dismissible]host. - Focus — the action link and dismiss button show a visible
:focus-visiblering (--re-shadow-focus); the dismiss ring is an outer ring, since the band’s block padding gives it room to render unclipped. There is no focus trap — a banner is inline page content, not a modal overlay, so focus is never captured or returned. - Semantics — mark up a persistent strip as
<aside>or<div role="region">with anaria-label; for a strip injected at runtime, userole="status"(a polite live region) so assistive tech announces it without stealing focus. The leading.re-banner__iconis decorative and carriesaria-hidden="true", and the dismiss button has an explicitaria-label(“Dismiss”) because its only child is a×glyph. - Notes — solid emphasis (
data-emphasis="solid") uses the*-700status fill withtext-on-accenttext, and the dismiss×keeps fullcurrentColor(not a translucent mix), so message, link, icon, and close button all clear WCAG AA contrast on both subtle and solid fills, in light and dark mode. Logical properties (margin-inline-start,border-block) keep the layout and the inline-end dismiss button correct underdir="rtl". See the accessibility guide for the system-wide baseline.