7 Pure CSS1 with JSPublished 2026-10-04Free · no sign-up
Eight badge styles: order status pills, number badges on icon buttons, presence dots on avatars, New and Sale tags on product cards, a solid, soft and outline set, Live and Beta labels, removable filter tags and verified and role badges next to names.
Pill badges for order and task states: Paid, Pending, Refunded, Failed and Draft. Each has a small dot plus readable text, uses soft background tints with dark text for strong contrast, and never relies on colour alone to carry the meaning.
Number badges pinned to the corner of icon buttons, such as a cart with 3 items or a message icon with 12 unread. Counts above 99 show 99+, and each button's accessible name includes the number so it is not only conveyed by the badge.
Presence indicators on avatars: online, away, busy and offline. The dot is a pseudo-element with a white ring so it stands out on any photo, and the status is also written in the image's alt text and a visible caption.
Product card badges for New, Sale with a percentage and Last few, positioned over the image corner. They are real text inside the card, so screen readers read them with the product, and the sale badge uses an angled clip-path edge.
One badge component in three visual weights: solid, soft and outline, across three sizes. The variants share one base class and change only background, border and padding through modifier classes, which keeps a design system tidy.
Badges that draw attention for live streams and beta features: a red Live badge with a pulsing dot, and a gradient Beta badge with a soft glow. The pulse is a scaling ring that stops for reduced motion, while the text stays perfectly still.
Applied filter tags with a remove button on each, plus a Clear all link. Each remove button is named Remove filter: Cotton and so on, and focus moves to the next tag after one is removed so keyboard users do not lose their place.
const ul = document.querySelector('.rm ul');
ul.addEventListener('click', e => {
const b = e.target.closest('button'); if (!b) return;
const li = b.parentElement, next = li.nextElementSibling || li.previousElementSibling;
li.remove();
(next ? next.querySelector('button') : document.querySelector('.clr')).focus();
});
document.querySelector('.clr').addEventListener('click', () => { ul.innerHTML = ''; });
08. Verified and Role Badges
ProfileIcon
Inline badges that sit next to a name: a verified check, an Admin role and a Top seller label with a star. The verified check is an SVG with an accessible title, so the verification is announced rather than only shown as a blue tick.
A badge should be real text that makes sense on its own, such as Paid or 3 items. Colour helps scanning, but the word carries the meaning for screen readers and people with colour vision deficiency.
Counts on buttons
When a badge shows a number on an icon button, include the number in the button's accessible name, for example Cart, 3 items, and hide the visual badge from screen readers so it is not read twice.
Contrast in small text
Badges use small text, so contrast matters more. Soft badges here pair a light tint with a dark text colour of the same hue, which keeps contrast high without heavy blocks of colour.
Removable tags
A remove button inside a tag needs a full name such as Remove filter: Cotton. After removing a tag, move focus to the next one so keyboard users stay in place.
Frequently asked questions
Do badges need JavaScript?
Only the removable tags demo.
How do I show 99+?
Cap the number in your template and say more than 99 in the accessible name, as the count demo does.
Can badges animate?
Keep animation small, like the Live pulse, and stop it with prefers-reduced-motion.