Badge
Label or indicator
Intent
Badge is a small label: a status pill next to a row, a count on a tab, a tag on a list item, a version marker in a page header. It carries short text -- a word, a digit, a short phrase -- and communicates category, status, or count at a glance. Use alert when the message needs a full sentence and persistence; use a plain text label when no chrome is needed.
Badge is an element-agnostic atom: render as
<span> for static labels, as
<a> for links, as <button>
for actions. Interactive rendering gets hover, focus, and
disabled styling automatically.
Basic usage
A bare .badge uses primary tones and pill-shaped
corners. Drop it inline with surrounding text, or pair with
.cluster when
grouping several.
<span class="badge">New</span>Variants
Color
Status tones remap the scoped tokens to the matching
semantic color family. The default (no modifier) uses primary
tones and reads as informational -- the most common "here is a
marker" default. Reach for .is-neutral when the
badge shouldn't draw attention.
<div class="cluster is-tight">
<span class="badge">Default</span>
<span class="badge is-neutral">Neutral</span>
<span class="badge is-accent">Accent</span>
<span class="badge is-success">Success</span>
<span class="badge is-warning">Warning</span>
<span class="badge is-danger">Danger</span>
</div>Shape
Badge's default shape is a pill (--radius-pill),
optimized for short text. Other shape modes cover the rest:
.as-square for tag-style corners where a pill
reads too playful, and .as-circle for counts and
step indicators.
.as-circle sets a minimum inline and block size
so a single digit stays round, but inline padding lets wider
content (double digits, a short word) push the width past the
minimum and turn the circle into a pill gracefully. The block
axis never grows past the minimum, so circles stay aligned
inside flex rows without aspect-ratio fights.
<div class="cluster is-tight">
<span class="badge">Pill</span>
<span class="badge as-square">Square</span>
<span class="badge as-circle">3</span>
<span class="badge as-circle">42</span>
<span class="badge as-circle">128</span>
</div>Interactive
Render badge as <a> or
<button> for filterable tags, removable
chips, or navigable labels. The element gets hover darkening, a
focus ring keyed to --color-focus, and a disabled
state that binds to either :disabled (native) or
[aria-disabled="true"] (for non-button
invokers that need a disabled look).
<div class="cluster is-tight">
<a class="badge" href="#">Filter: docs</a>
<button class="badge is-accent" type="button">Apply</button>
<button class="badge is-danger" type="button" disabled="">Disabled</button>
<a class="badge is-neutral" href="#" aria-disabled="true">ARIA-disabled link</a>
</div>Composed patterns
Badge doesn't own its own layout -- it composes with existing primitives for grouping, positioning, and dismissal. Three common pairings:
Grouping with .cluster
Several badges on one line -- status pills, tag lists, metadata
rows -- use
.cluster.is-tight
to handle spacing and wrap without the row overflowing on
narrow viewports.
<div class="cluster is-tight">
<span class="badge is-success">Active</span>
<span class="badge is-neutral">v0.1.0</span>
<span class="badge is-warning">Beta</span>
<span class="badge is-accent">Internal</span>
</div>Overlay with .anchor
A count or status dot positioned on a parent element --
notification count on a button, new-flag on an avatar -- uses
.anchor with
.anchor-overlay on the badge. The parent stays
its normal size; the badge sits at the corner without
displacing layout.
<div class="cluster is-relaxed">
<div class="anchor">
<button class="button" type="button">Inbox</button>
<span class="badge is-danger as-circle anchor-overlay" aria-label="3 unread">3</span>
</div>
<div class="anchor">
<button class="button" type="button">Drafts</button>
<span class="badge is-accent anchor-overlay">New</span>
</div>
</div>Dismissible with .dismiss
Removable chips -- filter pills, tag chooser selections -- add
data-dismissible to the badge and a
<button class="dismiss"> child. The unified
dismiss behavior (see dismiss)
walks up to the nearest [data-dismissible]
ancestor and removes it on click.
<div class="cluster is-tight">
<span class="badge is-neutral" data-dismissible="">
Draft
<button class="dismiss" type="button" aria-label="Remove draft filter">×</button>
</span>
<span class="badge is-neutral" data-dismissible="">
Priority: high
<button class="dismiss" type="button" aria-label="Remove priority filter">×</button>
</span>
<span class="badge is-neutral" data-dismissible="">
Assigned to me
<button class="dismiss" type="button" aria-label="Remove assignment filter">×</button>
</span>
</div>Class reference
.badge-- the atom. Render as<span>,<a>, or<button>; interactive states apply automatically to the latter two..is-neutral,.is-accent,.is-success,.is-warning,.is-danger-- color variants. Default (no modifier) uses primary..as-square-- tag-style corners (--radius-sm)..as-circle-- round shape with a minimum inline/block size; stretches to pill for wide content.
Customization
Full token list and defaults:
src/css/badge.css.
Accessibility
-
Interactive focus. Badges rendered as
<a>or<button>get a:focus-visibleoutline automatically. Static<span>badges don't -- they're not focusable, and don't need to be. -
Disabled state. Use the native
disabledattribute on a<button>when the action is unavailable. For links or other invokers that can't carrydisabled, addaria-disabled="true"; badge styles both the same way.pointer-events: nonekeeps the element inert in either case. -
Counts need context. A bare "3" inside
.as-circleis ambiguous to a screen reader. Usearia-label="3 unread"on the badge, or put a descriptive.visually-hiddenspan adjacent to the digit. The.anchoroverlay pattern above shows thearia-labelvariant.
CSS Reference: Badge
Small label or status indicator
Source: src/css/badge.css
Tokens
| Token | Default | Description |
|---|---|---|
--badge-bg | var(--color-primary-subtle) | Background color for the badge |
--badge-color | var(--color-primary-text) | Text color for the badge |
--badge-border | var(--color-primary-border) | Border color for the badge |
--badge-radius | var(--radius-pill) | Border radius, defaults to pill shape |
--badge-padding | var(--ui-pad-y-dense) var(--ui-pad-x-compact) | Inner padding for the badge |
--dismiss-padding | var(--ui-pad-square-tight) | Padding override for an embedded dismiss button |
Slots
| Slot | Description |
|---|---|
.dismiss | Embedded dismiss button with tighter padding |
Classes
| Class | Description |
|---|---|
.badge | component root |
.is-neutral | Neutral color variant with muted text |
.is-accent | Accent color variant |
.is-danger | Danger color variant |
.is-success | Success color variant |
.is-warning | Warning color variant |
.as-square | Tag-style square corners instead of pill |
.as-circle | Circular shape for counts and step indicators |