Home / Snippets / UI Components /

Chip/tag

Compact chip/tag component with optional close button. Ideal for filters, categories, and selected items.

Default Accent Success Warning CSS Design
Widely Supported
uino-js

Quick implementation

/* HTML:
   <span class="chip">Label</span>
   <span class="chip chip--accent">
     Label
     <button type="button" class="chip-close" aria-label="Remove Label">&times;</button>
   </span>
*/

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1;
  background: oklch(0.25 0.02 260);
  color: oklch(0.93 0.01 260);
  border: 1px solid oklch(0.35 0.02 260);
}

.chip--accent {
  background: oklch(0.28 0.08 265);
  color: oklch(0.85 0.12 265);
  border-color: oklch(0.42 0.14 265);
}

.chip--success {
  background: oklch(0.26 0.07 145);
  color: oklch(0.82 0.12 145);
  border-color: oklch(0.40 0.12 145);
}

.chip--warning {
  background: oklch(0.27 0.07 75);
  color: oklch(0.85 0.13 75);
  border-color: oklch(0.42 0.13 75);
}

.chip-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  border: none;
  background: oklch(1 0 0 / 0.12);
  color: inherit;
  cursor: pointer;
  font-size: 0.7rem;
  padding: 0;
  transition: background 0.15s ease;
}

.chip-close:hover {
  background: oklch(1 0 0 / 0.25);
}

.chip-close:focus-visible {
  outline: 2px solid oklch(0.72 0.19 265);
  outline-offset: 1px;
}

@media (prefers-reduced-motion: reduce) {
  .chip, .chip-close { transition: none; }
}

Prompt this to your LLM

Includes role, constraints, two framework variants, and edge cases to handle.

You are a senior frontend engineer building accessible UI components.

Goal: A chip/tag component with color variants and an optional dismiss button — pure CSS, no JavaScript for styling.

Technical constraints:
- Use border-radius: 999px for the pill shape.
- Color variants (default, accent, success, warning) use oklch() with matching background, text, and border at appropriate lightness levels.
- The close button must be a real <button> element with aria-label describing what it removes.
- Close button uses a circular background (oklch alpha) that darkens on hover.
- All transition properties must be wrapped in @media (prefers-reduced-motion: reduce).
- Use inline-flex with gap for label + close button alignment — no absolute positioning.

Framework variant (pick one):
A) Vanilla HTML + CSS — static markup with BEM-style modifier classes.
B) React component — accept label, variant (default | accent | success | warning), onRemove callback, and className props.

Edge cases to handle:
- Long labels: chip must truncate with ellipsis at a max-width, not overflow the container.
- No close button: chip renders as a plain <span> with no interactive element.
- Disabled state: lower opacity and suppress pointer events on the close button.
- Dense layouts: chips must wrap cleanly in a flex container with consistent gap.

Return HTML + CSS.

Why this matters in 2026

Chips are among the most overused yet under-engineered UI patterns. Most implementations reach for a library when the entire component is fewer than 30 lines of CSS. The pill shape, tinted variants, and dismissible close button all express meaning — status, category membership, removability — without text labels. Getting this right in pure CSS means zero JavaScript overhead and full server-render compatibility.

The logic

border-radius: 999px creates the pill regardless of content width without needing to know the element's height. Each color variant uses three coordinated oklch() values — background at low lightness, border a step higher, and text at high lightness — all on the same hue angle. This keeps variants visually consistent even as the hue shifts across the spectrum. The close button is a true <button> rather than a styled <span>, which gives free keyboard accessibility and fires click events without JavaScript listeners needing to detect which element was tapped.

Accessibility & performance

Each close button carries an aria-label that identifies what will be removed (e.g. "Remove Warning") rather than just saying "close", which is meaningless out of context for screen reader users. The :focus-visible ring on the close button uses outline-offset so it clears the circular background. Transitions on background are the only animated properties, which avoids layout or paint costs. The prefers-reduced-motion guard disables them entirely for users who opt out of motion.