Badges


Simple Badges

Basic badges for categorization and labels.

Default Primary Secondary
<span class="Badge">Default</span>
<span class="Badge Badge--primary">Primary</span>
<span class="Badge Badge--secondary">Secondary</span>

Status Badges

Semantic badges to indicate states like success, warning, or error.

Active Pending Failed New
<span class="Badge Badge--success">Active</span>
<span class="Badge Badge--warning">Pending</span>
<span class="Badge Badge--error">Failed</span>
<span class="Badge Badge--info">New</span>

Badge Sizes

Badges come in three sizes: small, medium (default), and large.

Small Medium Large
<span class="Badge Badge--primary Badge--small">Small</span>
<span class="Badge Badge--primary">Medium</span>
<span class="Badge Badge--primary Badge--large">Large</span>

Pill Badges

Fully rounded badges for a softer appearance.

Default Primary Success Warning Error
<span class="Badge Badge--pill Badge--primary">Primary</span>
<span class="Badge Badge--pill Badge--success">Success</span>

Outline Badges

Badges with transparent background and colored border.

Default Primary Success Warning Error
<span class="Badge Badge--outline Badge--primary">Primary</span>
<span class="Badge Badge--outline Badge--success">Success</span>

Badges with Icons

Add icons for visual reinforcement.

Complete Pending Error Info
<span class="Badge Badge--success">
    <i class="ph ph-check-circle Badge-icon"></i>
    Complete
</span>
New Feature Settings
<span class="Badge Badge--primary">
    New Feature
    <i class="ph ph-arrow-right Badge-icon Badge-icon--trailing"></i>
</span>

Dot Indicator

Minimal status indicator without text.

<span class="Badge Badge--dot Badge--success"></span>
<span class="Badge Badge--dot Badge--error"></span>
Online
Away
Offline

Count Badges

Badges for displaying numeric counts.

5 12 99+
<span class="Badge Badge--count">5</span>
<span class="Badge Badge--count Badge--primary">12</span>
<span class="Badge Badge--count Badge--error">99+</span>

Badge Positioning

Common patterns for positioning badges relative to other elements.

<button class="Button Button--icon" style="position: relative;">
    <i class="ph ph-bell"></i>
    <span class="Badge Badge--count Badge--error Badge--positioned">3</span>
</button>
User
User
User 5
<div style="position: relative; display: inline-block;">
    <img src="..." class="Avatar" alt="User" loading="lazy" decoding="async">
    <span class="Badge Badge--dot Badge--success Badge--avatar"></span>
</div>

Interactive Badges

Badges that can be clicked or dismissed.

Filter Active Tag Name
<span class="Badge Badge--primary Badge--dismissible">
    Filter Active
    <button class="Badge-dismiss" aria-label="Remove filter">
        <i class="ph ph-x"></i>
    </button>
</span>
<a href="#" class="Badge Badge--primary Badge--clickable">View Details</a>

Common Patterns

Table Row Status

Order #12345 Delivered Today
Order #12346 In Transit Est. Tomorrow
Order #12347 Cancelled —

User List with Status

Sarah
Sarah Chen
Online
Admin
John
John Smith
Away
Editor
Mike
Mike Johnson
Offline
Viewer

Feature Tags

Featured New

Advanced Analytics

Track performance with real-time dashboards and detailed reports.

Charts Exports API

Notification Header

Notifications

4 new

Customization

Override badge styles using CSS custom properties:

/* Custom brand badge */
.Badge--brand {
  background-color: oklch(60% 0.15 280 / 0.15);
  color: oklch(50% 0.15 280);
}

/* Larger count badge */
.Badge--count-lg {
  min-width: 28px;
  height: 28px;
  font-size: 0.8rem;
  padding: 0 var(--space-2);
}

/* Animated dot (pulsing) */
.Badge--dot.Badge--pulse {
  animation: badge-pulse 2s infinite;
}

@keyframes badge-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

/* Bordered badge */
.Badge--bordered {
  border: 1.5px solid currentColor;
  background-color: transparent;
}

/* Custom spacing for tight layouts */
.Badge--tight {
  padding: 0 var(--space-1);
  font-size: 0.65rem;
}

API Reference

Base & Variant Classes

ClassDescription
.BadgeBase badge styling
.Badge--primaryPrimary color variant
.Badge--secondarySecondary/neutral color variant
.Badge--successSuccess/positive state
.Badge--warningWarning/caution state
.Badge--errorError/danger state
.Badge--infoInformational state

Size & Shape Classes

ClassDescription
.Badge--smallSmaller badge size
.Badge--largeLarger badge size
.Badge--pillFully rounded pill shape
.Badge--outlineTransparent background with border
.Badge--dotMinimal dot indicator (no text)
.Badge--countCircular count badge

Positioning & Interactive Classes

ClassDescription
.Badge--positionedAbsolute positioning for overlays
.Badge--avatarPositioning for avatar overlays
.Badge--dismissibleBadge with remove button
.Badge--clickableInteractive link/button badge
.Badge-iconLeading icon styling
.Badge-icon--trailingTrailing icon positioning
.Badge-dismissDismiss button inside badge

Attributes

AttributeDescription
aria-labelRequired for dot indicators without visible text
aria-hiddenUse on count badges when count is announced via parent

CSS Reference

/* Base Badge */
.Badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--r-s);
  font-family: var(--ff-b);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  background-color: var(--bg-s);
  color: var(--fg);
  border: 1px solid transparent;
}

/* Colors */
.Badge--primary {
  background-color: oklch(60% 0.15 250 / 0.15);
  color: oklch(50% 0.15 250);
}

.Badge--secondary {
  background-color: var(--bg-s);
  color: var(--fg-3);
  border-color: var(--bd);
}

.Badge--success {
  background-color: oklch(65% 0.15 150 / 0.15);
  color: oklch(45% 0.15 150);
}

.Badge--warning {
  background-color: oklch(75% 0.15 80 / 0.15);
  color: oklch(50% 0.15 80);
}

.Badge--error {
  background-color: oklch(55% 0.2 25 / 0.15);
  color: oklch(50% 0.2 25);
}

.Badge--info {
  background-color: oklch(65% 0.15 220 / 0.15);
  color: oklch(50% 0.15 220);
}

/* Sizes */
.Badge--small {
  padding: 0 var(--space-1);
  font-size: var(--fs-2xs);
}

.Badge--large {
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-base);
}

/* Pill */
.Badge--pill {
  border-radius: var(--r-f);
}

/* Outline */
.Badge--outline {
  background-color: transparent;
}

.Badge--outline.Badge--primary {
  border-color: oklch(60% 0.15 250);
  color: oklch(60% 0.15 250);
}

.Badge--outline.Badge--success {
  border-color: oklch(55% 0.15 150);
  color: oklch(55% 0.15 150);
}

.Badge--outline.Badge--warning {
  border-color: oklch(60% 0.15 80);
  color: oklch(60% 0.15 80);
}

.Badge--outline.Badge--error {
  border-color: oklch(55% 0.2 25);
  color: oklch(55% 0.2 25);
}

/* Dot */
.Badge--dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 50%;
  background-color: var(--fg-3);
}

.Badge--dot.Badge--success {
  background-color: oklch(55% 0.15 150);
}

.Badge--dot.Badge--warning {
  background-color: oklch(70% 0.15 80);
}

.Badge--dot.Badge--error {
  background-color: oklch(55% 0.2 25);
}

.Badge--dot.Badge--primary {
  background-color: var(--accent);
}

/* Count */
.Badge--count {
  min-width: 20px;
  height: 20px;
  padding: 0 var(--space-1);
  border-radius: var(--r-m);
  text-align: center;
  justify-content: center;
}

/* Positioning */
.Badge--positioned {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  font-size: var(--fs-2xs);
}

.Badge--avatar {
  position: absolute;
  bottom: 0;
  right: 0;
  border: 2px solid var(--bg);
}

/* Icon */
.Badge-icon {
  font-size: 0.9em;
}

.Badge-icon--trailing {
  order: 1;
}

/* Dismissible */
.Badge--dismissible {
  padding-right: var(--space-1);
}

.Badge-dismiss {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  padding: 0;
  margin-left: var(--space-1);
  background: none;
  border: none;
  border-radius: 50%;
  cursor: pointer;
  color: inherit;
  opacity: 0.7;
  transition: opacity var(--dur-f);
}

.Badge-dismiss:hover {
  opacity: 1;
  background-color: oklch(0% 0 0 / 0.1);
}

/* Clickable */
.Badge--clickable {
  cursor: pointer;
  text-decoration: none;
  transition: background var(--dur-f), color var(--dur-f);
}

.Badge--clickable:hover {
  filter: brightness(0.95);
}

Accessibility

Color Independence

<!-- Don't rely on color alone — include text or icons -->
<span class="Badge Badge--success">
    <i class="ph ph-check-circle Badge-icon"></i>
    Complete
</span>

<!-- Not just color -->
<span class="Badge Badge--error">Error</span>

Screen Reader Context

<!-- Provide context for count badges -->
<button class="Button Button--icon" aria-label="Notifications, 3 unread">
    <i class="ph ph-bell"></i>
    <span class="Badge Badge--count" aria-hidden="true">3</span>
</button>

<!-- For status dots, use aria-label -->
<span class="Badge Badge--dot Badge--success" aria-label="Online"></span>

Dismissible Badges

<!-- Always provide accessible dismiss button -->
<span class="Badge Badge--dismissible">
    Filter: Active
    <button class="Badge-dismiss" aria-label="Remove Active filter">
        <i class="ph ph-x"></i>
    </button>
</span>

Best Practices

Do

  • ✓ Keep text short — 1-2 words maximum
  • ✓ Use semantic colors — Green for success, red for errors
  • ✓ Include icons for clarity — Helps users with color blindness
  • ✓ Position consistently — Same placement across similar elements
  • ✓ Use for quick scanning — Badges should be glanceable

Don’t

  • ✗ Overuse badges — Too many reduces impact
  • ✗ Rely on color alone — Always pair with text or icons
  • ✗ Use for long content — That’s what labels or tags are for
  • ✗ Mix too many colors — Stick to 2-3 per view
  • ✗ Hide important info — Critical statuses need more than a dot

See also