Badge
Compact label for counts, status, or category tags, with shared intents and variants.
A badge is information, never a control: counts, status, categories. It is
non-interactive by nature — for a selectable option use
.choice-card.chip; for a value produced by
a widget that can be removed (combobox multi-value), the widget owns the
removable tag (see combobox).
- Supports intent colors.
- Soft by default. Use
.solidfor counters and notification badges, or.outlinefor quieter emphasis. - Empty badges are solid status dots: visual variants such as
.softand.outlinedo not change their fill. - Use
.smor.lgto scale the badge locally. - Use
.compactor.spaciouson a context to change geometry without changing the label or icon size. - Can be used inline in headings.
- Can be used as a count badge.
- Can be used as a stable dot badge when empty and given an accessible name.
- Empty badges render as dots. The element must be truly empty: no text and no whitespace.
A badge is content-sized: it never stretches to fill its container, even as a
direct child of .stack (where flex children otherwise stretch), and a flex
parent never compresses it (flex: none). Use inline-size: 100% — or the
optional .inline-size-full utility — when a full-width badge is intentional.
Related terms: chip, tag, pill, removable tag, user chip, mention, assignee.
Class reference
| Class | Kind | Description |
|---|---|---|
.badge | Component | Compact label; soft by default. |
.badge:empty | Composition | Truly-empty badge renders as a solid dot. |
.dot | Composition | Status dot inside a badge. |
.avatar | Composition | Leading avatar sized to the badge. |
| Shared intents | Intent | .primary, .secondary, .success, … |
| Shared variants | Variant | .solid, .outline, .surface. |
.sm / .lg | Size | Smaller or larger optical scale. |
The shared intents are .primary, .secondary, .success, .warning and
.danger. The variants set emphasis: .solid is filled, .outline bordered,
.surface untinted.
Basic usage
<span class="badge">Default</span>
<span class="badge secondary">Secondary</span>
<span class="badge success">Success</span>
<span class="badge warning">Warning</span>
<span class="badge danger">Danger</span>
<span class="badge success outline">Outline success</span>
<span class="badge warning soft">Soft warning</span>
<span class="badge primary solid">Solid primary</span>
<span class="badge success solid">Solid success</span>
<span class="badge danger solid">Solid danger</span>
In a title
New features New
<h2>New features <span class="badge success soft">New</span></h2>
Composed
<button type="button" class="btn ghost" aria-label="Notifications">
<i class="ti ti-bell" aria-hidden="true"></i>
<span class="badge danger solid" aria-label="12 unread notifications">12</span>
</button>
<button type="button" class="btn secondary soft" aria-label="Notifications">
<i class="ti ti-bell" aria-hidden="true"></i>
<span class="badge danger" aria-label="Errors!"></span>
</button>
Status dot
<span class="badge success" aria-label="Online"></span>
An autonomous dot conveys state without visible text, so give it an accessible name.
For a dot beside a label, put the shared .dot utility inside the badge. It
paints with currentColor, so it follows the badge ink instead of needing the
intent class repeated on it.
<span class="badge warning">
<span class="dot" aria-hidden="true"></span>
In progress
</span>
<span class="badge danger">
<span class="dot" aria-hidden="true"></span>
Blocked
</span>
<span class="badge success">
<span class="dot" aria-hidden="true"></span>
Completed
</span>
Custom status or category dots define a custom intent (--intent /
--intent-fg); --ui-* controls treatment, while empty dots intentionally
remain solid.
Color marker
Use an empty badge as a compact intent-colored marker in legends and status labels. When adjacent text carries the same information, keep the marker decorative.
<span class="badge primary" aria-hidden="true"></span>
Regular
Size variants
<span class="badge success sm">Small</span>
<span class="badge success">Default</span>
<span class="badge success lg">Large</span>
A badge keeps its size inside a .compact or .spacious context: its
geometry is intrinsic to its label. Use .sm / .lg for a smaller or larger
badge.
With an icon
Decorative SVG, image, or [aria-hidden="true"] children follow
--badge-icon-size. An .avatar keeps its own sizing (see below).
<span class="badge success">
<i class="ti ti-rosette-discount-check" aria-hidden="true"></i>
Verified
</span>
<span class="badge warning">
<i class="ti ti-clock" aria-hidden="true"></i>
Pending
</span>
<span class="badge danger solid">
<i class="ti ti-alert-circle" aria-hidden="true"></i>
Failed
</span>
With an avatar
Put an .avatar first in the badge for a person chip: mention,
assignee, contributor, author. The avatar follows the badge size, so the pill
keeps its height and .sm / .lg scale both together. Wrap the chips in a
.cluster to let them wrap.
<div class="cluster tight">
<a href="#" class="badge lg">
<span class="avatar">
<img src="https://mockmind-api.uifaces.co/content/human/219.jpg" alt="" />
</span>
@jane-doe
</a>
<a href="#" class="badge lg">
<span class="avatar success"><abbr>RM</abbr></span>
@rin-moreau
</a>
<span class="badge primary">
<span class="avatar"><abbr>AM</abbr></span>
Ada Morgan
<button class="close" type="button" aria-label="Remove Ada Morgan"></button>
</span>
</div>
Keep alt="" when the handle or name sits next to the image. Initials fit
the default and .lg sizes; use an image on .sm.
Loading status
A decorative spinner follows the badge color and optical size.
<span class="badge danger sm">
<span class="spinner" aria-hidden="true"></span>
Deleting
</span>
<span class="badge sm">
Generating
<span class="spinner" aria-hidden="true"></span>
</span>
Custom sizing
Override the existing hooks when the three-step scale does not fit the content.
<span class="badge primary" style="--badge-size: 2rem; --badge-font-size: var(--font-size-md);">
Prominent
</span>
Removable tag pattern
Use .badge soft for tag visuals. Add a direct .close button only when the tag can actually be removed. There is no separate chip component.
For a compact action or filter, use .btn.sm instead; badges describe content
and must not be turned into toggle controls merely to obtain a compact shape.
Never put a .close inside a .choice-card.chip label: the label is already
an interactive target driving its checkbox/radio, and a nested button would mix
two interactive targets. A removable tag next to a selectable chip is a sibling
(a widget tag or a .badge + .close), never a child of the label.
Put the close last. It mirrors a leading avatar: a disc inside the pill at the same inset, so a fill or the hover wash never leaves the pill. On small badges the disc is small; an invisible hit area keeps the pointer target at 24px.
<span class="badge primary soft sm">
Design
<button class="close" type="button" aria-label="Remove Design"></button>
</span>
<span class="badge primary soft">
Design
<button class="close" type="button" aria-label="Remove Design"></button>
</span>
<span class="badge primary soft lg">
Design
<button class="close" type="button" aria-label="Remove Design"></button>
</span>
CSS hooks
--badge-radius— corner radius.--badge-size— minimum block size; also the square size of an:emptydot badge.--badge-dot-size— size of an:emptydot badge.--badge-font-size— label font size.--badge-icon-size— decorative child size;1emfollows the label by default.--badge-pad-x— inline padding. Derived from--badge-size, so it stays proportional to the pill; set it to opt out.--close-size/--close-icon-size— the badge declares them for its.close; set them on the badge to change them.