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.

New
<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.

Default Neutral Accent Success Warning Danger
<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.

Pill Square 3 42 128
<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.

Active v0.1.0 Beta Internal
<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.

3
New
<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.

Draft Priority: high Assigned to me
<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-visible outline automatically. Static <span> badges don't -- they're not focusable, and don't need to be.
  • Disabled state. Use the native disabled attribute on a <button> when the action is unavailable. For links or other invokers that can't carry disabled, add aria-disabled="true"; badge styles both the same way. pointer-events: none keeps the element inert in either case.
  • Counts need context. A bare "3" inside .as-circle is ambiguous to a screen reader. Use aria-label="3 unread" on the badge, or put a descriptive .visually-hidden span adjacent to the digit. The .anchor overlay pattern above shows the aria-label variant.

CSS Reference: Badge

Small label or status indicator

Source: src/css/badge.css

Tokens

TokenDefaultDescription
--badge-bgvar(--color-primary-subtle)Background color for the badge
--badge-colorvar(--color-primary-text)Text color for the badge
--badge-bordervar(--color-primary-border)Border color for the badge
--badge-radiusvar(--radius-pill)Border radius, defaults to pill shape
--badge-paddingvar(--ui-pad-y-dense) var(--ui-pad-x-compact)Inner padding for the badge
--dismiss-paddingvar(--ui-pad-square-tight)Padding override for an embedded dismiss button

Slots

SlotDescription
.dismissEmbedded dismiss button with tighter padding

Classes

ClassDescription
.badgecomponent root
.is-neutralNeutral color variant with muted text
.is-accentAccent color variant
.is-dangerDanger color variant
.is-successSuccess color variant
.is-warningWarning color variant
.as-squareTag-style square corners instead of pill
.as-circleCircular shape for counts and step indicators