ui.css · Cross-system: Cross-system reference § Content
.badge — small status pill for labels, counts, and tags. Always non-interactive. For actionable
pills, use .btn.sm instead. A badge is never a form field's value:
a value the caller may not change stays a field, so that it does not read as a control
(Form field states).
A <span> (or other inline element) with class="badge" and optionally one
variant class, plus the stackable .pulse modifier. Supported variants and modifiers are listed on
Modifiers.
The badge is an inline-flex row with a --size-1 gap, so a leading
<ui-icon> next to the label needs no extra spacing markup:
<span class="badge outline"><ui-icon name="user"></ui-icon> Owner</span>.
.badge — default (brand-colored fill)..secondary — muted surface fill..outline — transparent fill with border..brand — explicit brand color (alias for default; useful for clarity alongside other variants)..destructive — error / failure status (red). The same word and the same fill as
.btn.destructive: buttons warn about an action, while badges report its outcome..warning — an allowed but unusual state (orange) that needs attention. Use it for a
deliberate exception, not for a failure — that is .destructive..cancelled — cancelled / inactive status (muted grey).
.destructive, .warning and .cancelled use dark backgrounds with white text in both light and dark mode, keeping their appearance consistent. .warning and .cancelled are specific to badges because they describe status rather than an action. This is why
Modifiers lists them as badge-only while
.outline and .destructive are shared.
.pulse — live state
.pulse is a modifier rather than a variant: it
composes with any variant above and fades
the badge's opacity on a 2 s loop, to indicate ongoing activity — "Recording in
progress". For that fade, reach for this class and not Open Props' --animation-pulse,
which scales the element instead of fading it. The animation stops entirely under
prefers-reduced-motion: reduce; the badge label still conveys the state.
| plain | .pulse | |
|---|---|---|
| .badge | Default | Default |
| .badge.secondary | Secondary | Secondary |
| .badge.outline | Outline | Outline |
| .badge.brand | Brand | Brand |
| .badge.destructive | Failed | Failed |
| .badge.warning | Warning | Warning |
| .badge.cancelled | Cancelled | Cancelled |
Common uses: language tags on cards, status pills on jobs, counts on notification icons.
aria-label on the parent or include visually-hidden context text (<span class="visually-hidden">unread notifications</span>).<button class="btn sm">.
See Cross-system reference § Content. The Badge row
maps ours to Open UI's Badge research and Bootstrap's .badge; Material Web and APG have
no badge of their own. The neighbouring Tag / Chip row is where Material's
md-chip sits — a static chip is this .badge, while an interactive,
removable chip is <ui-combobox chips multiple>.
.btn — for actionable pills.<article>) — badges often sit in .card-title.readonly, not a badge.<ui-notifications> — the count bubble on the bell is
not this class: the component styles its own .ui-notifications-count, positioned over
the trigger and coloured by severity. <ui-statusbar> does the
same with .ui-statusbar-count. Use .badge for a count that sits inline in the text
flow, the way the notification count does in the In context demo above.