Skip to content

Alert

.bp-alert is a block-level feedback element for inline, persistent contextual messages. It supports four semantic variants (info, success, warning, error), an optional dismiss button, and a --accent modifier that adds a colored left stripe. No JavaScript is required for static alerts — a four-line snippet handles dismissal when needed.

Info

Heads up

Your account will be migrated to the new platform on June 1.

<div class="bp-alert bp-alert--info" role="status">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Heads up</p>
<p class="bp-alert__body">Your account will be migrated to the new platform on June 1.</p>
</div>
</div>

Success

Changes saved

Your profile has been updated successfully.

<div class="bp-alert bp-alert--success" role="status">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Changes saved</p>
<p class="bp-alert__body">Your profile has been updated successfully.</p>
</div>
</div>

Warning

<div class="bp-alert bp-alert--warning" role="alert">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Session expiring</p>
<p class="bp-alert__body">Your session will expire in 5 minutes. Save your work.</p>
</div>
</div>

Error

<div class="bp-alert bp-alert--error" role="alert">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Payment failed</p>
<p class="bp-alert__body">We could not charge your card. Please update your payment method.</p>
</div>
</div>

Add bp-alert--dismissible for visual affordance and include a bp-alert__close button. JS sets hidden to remove the alert.

Dismissible

<div class="bp-alert bp-alert--warning bp-alert--dismissible" role="alert" id="demo-alert-dismiss">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Warning</p>
<p class="bp-alert__body">Your session will expire in 5 minutes.</p>
</div>
<button class="bp-alert__close" type="button" aria-label="Dismiss alert"
onclick="document.getElementById('demo-alert-dismiss').hidden = true">
<span aria-hidden="true">&times;</span>
</button>
</div>

Add bp-alert--accent alongside a semantic variant to render a colored left stripe.

Accent stripe

Scheduled maintenance

The platform will be unavailable Saturday 02:00–04:00 UTC.

<div class="bp-alert bp-alert--info bp-alert--accent" role="status">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Scheduled maintenance</p>
<p class="bp-alert__body">The platform will be unavailable Saturday 02:00–04:00 UTC.</p>
</div>
</div>
<div class="bp-alert bp-alert--error bp-alert--accent" role="alert">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Payment failed</p>
<p class="bp-alert__body">We could not charge your card. Please update your payment method.</p>
</div>
</div>

Omit bp-alert__icon when an icon adds no value.

No icon

Read-only mode

You are viewing a snapshot. Changes are disabled.

<div class="bp-alert bp-alert--info" role="status">
<div class="bp-alert__content">
<p class="bp-alert__title">Read-only mode</p>
<p class="bp-alert__body">You are viewing a snapshot. Changes are disabled.</p>
</div>
</div>

Omit bp-alert__title for brief one-line messages.

No title

Invitation sent.

<div class="bp-alert bp-alert--success" role="status">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__body">Invitation sent.</p>
</div>
</div>
VariantRecommended roleLive region behavior
--inforole="status"Polite — announced at the next pause in speech
--successrole="status"Polite — announced at the next pause in speech
--warningrole="alert"Assertive — interrupts current speech immediately
--errorrole="alert"Assertive — interrupts current speech immediately

Use role="status" for non-critical updates (confirmations, informational notices). Use role="alert" when the user must act immediately or the situation is urgent. If the alert is present on page load and not injected dynamically, the live region role has no effect — but keep it for consistency and future dynamic use.

VariableDefaultDescription
--alert-bgcolor-mix tintBackground color (set by semantic variant)
--alert-colorvar(--bp-color-text)Text color
--alert-border-colorcolor-mix tintBorder color (set by semantic variant)
--alert-border-width1pxBorder width
--alert-border-radiusvar(--bp-radius-md)Border radius
--alert-padding-xvar(--bp-space-4)Horizontal padding
--alert-padding-yvar(--bp-space-3)Vertical padding
--alert-gapvar(--bp-space-3)Gap between icon, content, and close
--alert-accent-width4pxLeft stripe width
--alert-accent-colormatches border colorLeft stripe color (set by semantic variant)
--alert-title-sizevar(--bp-text-sm)Title font size
--alert-body-sizevar(--bp-text-sm)Body font size
ClassDescription
bp-alert--infoBlue — neutral notices, tips
bp-alert--successGreen — confirmation, completion
bp-alert--warningOrange — caution, expiration, at-risk state
bp-alert--errorRed — failure, blocked action, required user response
bp-alert--dismissibleVisual signal that the alert can be closed (no JS alone)
bp-alert--accentAdds a colored left stripe (combine with semantic)

Custom banner via public API

Full-width banner

Use public tokens to style the alert as a flush page banner.

<style>
.demo-alert--banner {
--alert-border-radius: 0;
--alert-border-width: 0;
--alert-padding-x: var(--bp-space-6);
--alert-padding-y: var(--bp-space-4);
--alert-accent-width: 6px;
}
</style>
<div class="bp-alert bp-alert--info bp-alert--accent demo-alert--banner" role="status">
<span class="bp-alert__icon" aria-hidden="true"></span>
<div class="bp-alert__content">
<p class="bp-alert__title">Full-width banner</p>
<p class="bp-alert__body">Use public tokens to style the alert as a flush page banner.</p>
</div>
</div>
  • Use role="status" for polite notices (--info, --success) and role="alert" for assertive ones (--warning, --error).
  • When injecting an alert dynamically, ensure the element with the live region role is in the DOM before content is inserted — the browser registers the live region on first parse.
  • The icon element must always carry aria-hidden="true" — it is decorative; variant meaning is conveyed by title and body text.
  • The close button requires an accessible name: aria-label="Dismiss alert". Never use an icon-only button without one.
  • Do not rely on color alone to communicate meaning — always pair color with text (title or body) or an icon with a text alternative.
  • If the alert is the only indicator of an error (e.g. form submission failure), move focus to the alert or its heading after injection.
APIAvailabilityUsed forWithout itPolyfill
color-mix() Widely available Baseline 2023 Tinted variant backgrounds, borderSolid token colorNone needed
  • --_bg, --_color, --_border-color, --_border-width, --_border-radius, --_padding-x, --_padding-y, --_gap, --_accent-width, --_accent-color — component-private, do not set directly.
  • The --accent left stripe is rendered via ::before. The root left border is set to transparent when --accent is active, and padding-left is increased by --_accent-width to preserve content alignment.
  • [hidden] dismiss: the close button sets hidden on the nearest .bp-alert ancestor. CSS rule .bp-alert[hidden] { display: none } removes it from layout without JS-toggled classes.

Minimal dismiss snippet (add once per page, no framework needed):

document.querySelectorAll('.bp-alert__close').forEach(btn => {
btn.addEventListener('click', () => btn.closest('.bp-alert').hidden = true)
})