Badge
span.badge
Badge — a small, static label attached to something else: "New", "Beta", "3 unread", a coloured dot beside a name.
Examples
Shipped
Beta
Pending
3 unread
Online
<span class="badge badge-success">Shipped</span>
<span class="badge badge-subtle badge-info">Beta</span>
<span class="badge badge-warning">Pending</span>
<span class="badge badge-danger badge-round">3<span class="sr-only"> unread</span></span>
<span class="badge badge-dot badge-success"><span class="sr-only">Online</span></span>A badge is not a status announcement. If the text changes at runtime nothing tells a screen reader — a badge is not focusable, so it may never be read at all.
Announcing a change needs a live region that existed before it, and that is the page’s decision, not this component’s.
Tokens 16
Level 2, declared on .badge itself. Set any of them on that selector to restyle this component without touching the skin.
| Token | Default |
|---|---|
| --badge-white-space | nowrap |
| --badge-bg | var(--color-surface-sunken) |
| --badge-border-color | var(--color-border-subtle) |
| --badge-border-width | var(--border-width) |
| --badge-color | var(--color-on-surface) |
| --badge-font-family | var(--font-secondary) |
| --badge-font-size | var(--font-size-xs) |
| --badge-font-weight | var(--font-weight-semibold) |
| --badge-gap | var(--space-1) |
| --badge-padding-block | 0.125rem |
| --badge-padding-inline | var(--space-2) |
| --badge-radius | var(--radius-sm) |
| --badge-dot-size | 0.625rem |
| --badge-min-size | 1.25rem |
| --badge-tint | var(--color-surface-sunken) |
| --badge-tint-border | var(--color-border-strong) |
Variants and states
Variants
.badge-danger.badge-dot.badge-info.badge-neutral.badge-round.badge-subtle.badge-success.badge-warning
State it reads
None.
Before you ship it
What you have to do 1 requirements
- Give a wordless badge a name.
.badge-dotand a bare number are not messages. A dot needs<span class="sr-only">Online</span>inside it, and "3" needs<span class="sr-only"> unread</span>after it — with the leading space, or it is announced as "3unread". Nothing in CSS can supply this and nothing can detect that it is missing. Let a badge wrap when its words are not yours. The default iswhite-space: nowrap, which is right for «New» and for a count and wrong for a status phrase coming out of a feed — and anowrapbadge inside anautogrid track holds that track open at the width of its longest string, which is a page scrolling sideways rather than a badge looking untidy. One declaration on the badge, or on a rule that selects it, hands the wrapping back: .cell-delay .badge { --badge-white-space: normal } Write it on the badge, not on the box around it.white-spaceis an inherited property and this knob is not: like every other token in this file it is declared on.badge, so a value set on an ancestor is shadowed by the component's own and the badge goes on refusing to wrap — silently, because the ancestor's declaration is perfectly valid and simply never read. A rule that selects the badge from the ancestor, as above, is the form that works. Nothing here can detect the case: whether the text is a label or a sentence is something only the consumer knows. Put the badge next to what it describes, inside the same element the screen reader will read as one phrase. A badge floated to the far side of a row is read after everything between it and its subject.
src/css/components/badge.css · npx mostlycss add badge