HTML Formatterhtmlformatteronline.com

Badges, tags and pills

Status badges, removable tags, counters and dot indicators.

cssbadgetagpilllabelstatus
<section>
  <h3>Status badges</h3>
  <p>
    <span class="badge ok">Shipped</span>
    <span class="badge wait">Packing</span>
    <span class="badge bad">Returned</span>
    <span class="badge info">Draft</span>
    <span class="badge neutral">Archived</span>
  </p>
</section>

<section>
  <h3>With a dot, for status at a glance</h3>
  <p>
    <span class="badge ok dotted">Live</span>
    <span class="badge wait dotted">Deploying</span>
    <span class="badge bad dotted">Failed</span>
  </p>
</section>

<section>
  <h3>Outline and solid</h3>
  <p>
    <span class="badge outline">Beta</span>
    <span class="badge solid">New</span>
    <span class="badge outline sm">v2.1</span>
  </p>
</section>

<section>
  <h3>Removable tags</h3>
  <ul class="tags">
    <li><span>linen</span><button type="button" aria-label="Remove tag linen">&times;</button></li>
    <li><span>wool</span><button type="button" aria-label="Remove tag wool">&times;</button></li>
    <li><span>made in Leeds</span><button type="button" aria-label="Remove tag made in Leeds">&times;</button></li>
  </ul>
</section>

<section>
  <h3>Counters</h3>
  <p class="counters">
    <button class="withcount" type="button">
      Inbox <span class="count">12</span>
    </button>
    <button class="withcount" type="button">
      Alerts <span class="count high">99+</span>
    </button>
    <button class="icononly" type="button" aria-label="Notifications, 3 unread">
      <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18 8a6 6 0 1 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9"/><path d="M10.3 21a2 2 0 0 0 3.4 0"/></svg>
      <span class="pip" aria-hidden="true"></span>
    </button>
  </p>
</section>

How it works

Custom properties do the colour variants. The base class defines two variables and each variant redefines them. Everything else — padding, radius, weight, the dot — is written once. Adding a sixth status is one line.

The dot inherits currentColor. One ::before rule works across all five variants because it takes the badge's own text colour. No per-variant dot rules.

Removable tags are a list. <ul> and <li>, so a screen reader announces "list, 3 items" and the user can skip past them. A row of divs says nothing.

Each remove button names its tag. aria-label="Remove tag linen", not "Remove". Three buttons all called "Remove" are useless in a screen reader's list of controls.

The counter uses tabular-nums. A count that changes from 9 to 10 shifts the button's width otherwise, which is very noticeable in a live interface.

The pip has a border in the button's background colour, which cuts a small gap between the dot and the icon behind it. That is what makes it read as sitting on top rather than being part of the icon.

Accessibility notes

Never rely on the colour alone. Every badge here has a word in it. A green pill with no text is meaningless to anyone who cannot distinguish it from the amber one, which is roughly one man in twelve.

The icon-only notification button carries the count in its aria-label — "Notifications, 3 unread" — and the red pip is aria-hidden, because the dot conveys nothing on its own.

If a count changes live, wrap it in a region with aria-live="polite" so the change is announced. Do not use assertive; an inbox counter is not worth interrupting someone mid-sentence.

Badge text at 12 pixels is at the small end of readable. Do not go below it, and keep the contrast on the tinted backgrounds above 4.5:1 — the amber combination is the one that usually fails.

Making it yours

The status colours here are the conventional four — green, amber, red, blue. Keep them consistent across a whole product; a green badge that means "archived" on one screen and "live" on another destroys the shorthand.

For a badge that is also a link or a filter, use an <a> or <button> rather than a <span>, and give it a hover state and a minimum height of 40 pixels for touch.

99+ rather than the real number past a threshold. Beyond about two digits the exact figure stops being useful and starts breaking your layout.

Related templates

Check your version

Once you have edited this, the HTML validator will catch any tag you left unclosed, and the formatter will tidy the indentation. Both run in your browser.