24 CSS Tags & Chips05 / 24
Deletable Pill Tag with Close Button
Pills that actually delete — with zero JavaScript. The × is a real focusable control (a restyled checkbox), so clicking or pressing Space collapses the pill with a width-and-scale exit animation; a CSS counter live-decrements the total; and one <button type="reset"> resurrects everything because the group is a <form>. The anatomy is the part worth stealing: text region and delete control are separate hit targets, exactly like Gmail's recipient chips.
Published Updated
The code
<section class="ctc-05" aria-label="Deletable pill tag demo">
<form class="ctc-05__stage">
<div class="ctc-05__wrap">
<header class="ctc-05__head">
<p class="ctc-05__kicker">Deletable pills · checkbox as close button</p>
<h1>Delete with ×. Undo with reset.</h1>
</header>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Skills <span class="ctc-05__n" aria-hidden="true"></span></p>
<div class="ctc-05__row ctc-05__row--skills">
<span class="ctc-05__pill"><span>Design systems</span><input type="checkbox" aria-label="Remove Design systems"></span>
<span class="ctc-05__pill"><span>Figma</span><input type="checkbox" aria-label="Remove Figma"></span>
<span class="ctc-05__pill"><span>CSS architecture</span><input type="checkbox" aria-label="Remove CSS architecture"></span>
<span class="ctc-05__pill"><span>Motion design</span><input type="checkbox" aria-label="Remove Motion design"></span>
<span class="ctc-05__pill"><span>Accessibility</span><input type="checkbox" aria-label="Remove Accessibility"></span>
<span class="ctc-05__pill"><span>Prototyping</span><input type="checkbox" aria-label="Remove Prototyping"></span>
<span class="ctc-05__pill"><span>User research</span><input type="checkbox" aria-label="Remove User research"></span>
</div>
</div>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Recipient variant — same anatomy, plus an initial block</p>
<div class="ctc-05__row">
<span class="ctc-05__pill ctc-05__pill--who" style="--h:250"><i>JR</i><span>jonas@relay.app</span><input type="checkbox" aria-label="Remove jonas@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:330"><i>MV</i><span>mara@relay.app</span><input type="checkbox" aria-label="Remove mara@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:150"><i>PA</i><span>priya@relay.app</span><input type="checkbox" aria-label="Remove priya@relay.app"></span>
</div>
</div>
<footer class="ctc-05__foot">
<button class="ctc-05__reset" type="reset">↺ Restore all</button>
<p>The × is the checkbox itself — <code>appearance:none</code>, drawn with two bars, focusable, Space-toggleable. Deletion is <code>.pill:has(:checked)</code> collapsing max-width, padding, margin and scale together.</p>
</footer>
</div>
</form>
</section><section class="ctc-05" aria-label="Deletable pill tag demo">
<form class="ctc-05__stage">
<div class="ctc-05__wrap">
<header class="ctc-05__head">
<p class="ctc-05__kicker">Deletable pills · checkbox as close button</p>
<h1>Delete with ×. Undo with reset.</h1>
</header>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Skills <span class="ctc-05__n" aria-hidden="true"></span></p>
<div class="ctc-05__row ctc-05__row--skills">
<span class="ctc-05__pill"><span>Design systems</span><input type="checkbox" aria-label="Remove Design systems"></span>
<span class="ctc-05__pill"><span>Figma</span><input type="checkbox" aria-label="Remove Figma"></span>
<span class="ctc-05__pill"><span>CSS architecture</span><input type="checkbox" aria-label="Remove CSS architecture"></span>
<span class="ctc-05__pill"><span>Motion design</span><input type="checkbox" aria-label="Remove Motion design"></span>
<span class="ctc-05__pill"><span>Accessibility</span><input type="checkbox" aria-label="Remove Accessibility"></span>
<span class="ctc-05__pill"><span>Prototyping</span><input type="checkbox" aria-label="Remove Prototyping"></span>
<span class="ctc-05__pill"><span>User research</span><input type="checkbox" aria-label="Remove User research"></span>
</div>
</div>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Recipient variant — same anatomy, plus an initial block</p>
<div class="ctc-05__row">
<span class="ctc-05__pill ctc-05__pill--who" style="--h:250"><i>JR</i><span>jonas@relay.app</span><input type="checkbox" aria-label="Remove jonas@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:330"><i>MV</i><span>mara@relay.app</span><input type="checkbox" aria-label="Remove mara@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:150"><i>PA</i><span>priya@relay.app</span><input type="checkbox" aria-label="Remove priya@relay.app"></span>
</div>
</div>
<footer class="ctc-05__foot">
<button class="ctc-05__reset" type="reset">↺ Restore all</button>
<p>The × is the checkbox itself — <code>appearance:none</code>, drawn with two bars, focusable, Space-toggleable. Deletion is <code>.pill:has(:checked)</code> collapsing max-width, padding, margin and scale together.</p>
</footer>
</div>
</form>
</section>.ctc-05,
.ctc-05 *,
.ctc-05 *::before,
.ctc-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ctc-05 {
--bg: oklch(0.965 0.008 250);
--ink: oklch(0.24 0.025 255);
--mut: oklch(0.5 0.02 255);
--line: oklch(0.88 0.012 250);
--acc: oklch(0.55 0.19 262);
--del: oklch(0.6 0.21 25);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
.ctc-05__stage {
width: 100%;
height: 100vh;
height: 100svh;
overflow-y: auto;
display: grid;
place-items: center;
padding: clamp(16px,4cqi,48px);
background: radial-gradient(75cqi 55cqi at 88% -12%,color-mix(in oklch,var(--acc) 13%,transparent),transparent 65%),var(--bg);
container: ctc05/inline-size;
border: 0;
}
.ctc-05__wrap {
width: min(680px,100%);
display: flex;
flex-direction: column;
gap: 16px;
}
.ctc-05__kicker {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--acc);
}
.ctc-05__head h1 {
font-size: clamp(24px,3.8cqi,38px);
font-weight: 800;
letter-spacing: -.03em;
margin: 8px 0 6px;
}
.ctc-05__panel {
background: oklch(0.995 0.002 250);
border: 1px solid var(--line);
border-radius: 18px;
padding: 16px 18px;
}
.ctc-05__lab {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.ctc-05__n {
display: inline-flex;
min-height: 22px;
align-items: center;
padding: 0 9px;
border-radius: 99px;
background: color-mix(in oklch,var(--acc) 13%,transparent);
color: var(--acc);
font-size: 11px;
font-weight: 800;
font-variant-numeric: tabular-nums;
letter-spacing: 0;
}
.ctc-05__row {
display: flex;
flex-wrap: wrap;
}
.ctc-05__row--skills {
counter-reset: ctc05n;
}
.ctc-05__row--skills .ctc-05__pill:not(:has(:checked)) {
counter-increment: ctc05n;
}
.ctc-05__n::after {
content: counter(ctc05n) " kept";
}
.ctc-05__pill {
display: inline-flex;
align-items: center;
gap: 9px;
min-height: 44px;
max-width: 320px;
padding: 0 9px 0 17px;
margin: 0 9px 9px 0;
border-radius: 99px;
border: 1.5px solid var(--line);
background: oklch(0.975 0.006 250);
font-size: 14px;
font-weight: 650;
white-space: nowrap;
overflow: hidden;
transition: max-width .38s,padding .38s,margin .38s,opacity .3s,scale .3s,border-color .2s,background .2s;
}
.ctc-05__pill:hover {
border-color: color-mix(in oklch,var(--acc) 40%,var(--line));
background: oklch(0.99 0.004 250);
}
.ctc-05__pill input {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 24px;
height: 24px;
border-radius: 50%;
border: 0;
background: color-mix(in oklch,var(--ink) 8%,transparent);
cursor: pointer;
transition: background .2s,rotate .25s;
outline-offset: 2px;
}
.ctc-05__pill input::before,
.ctc-05__pill input::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 1.8px;
border-radius: 2px;
background: var(--mut);
translate: -50% -50%;
transition: background .2s;
}
.ctc-05__pill input::before {
rotate: 45deg;
}
.ctc-05__pill input::after {
rotate: -45deg;
}
.ctc-05__pill input:hover,
.ctc-05__pill input:focus-visible {
background: color-mix(in oklch,var(--del) 16%,transparent);
rotate: 90deg;
}
.ctc-05__pill input:hover::before,
.ctc-05__pill input:hover::after,
.ctc-05__pill input:focus-visible::before,
.ctc-05__pill input:focus-visible::after {
background: var(--del);
}
.ctc-05__pill input:focus-visible {
outline: 2px solid var(--del);
}
.ctc-05__pill:has(:checked) {
max-width: 0;
padding-inline: 0;
margin: 0;
opacity: 0;
scale: .7;
pointer-events: none;
border-color: transparent;
}
.ctc-05__pill--who {
padding-left: 6px;
gap: 8px;
}
.ctc-05__pill--who i {
width: 30px;
height: 30px;
flex: none;
border-radius: 50%;
display: grid;
place-items: center;
font-style: normal;
font-size: 11px;
font-weight: 800;
color: oklch(0.99 0 0);
background: linear-gradient(140deg,oklch(0.68 0.13 var(--h)),oklch(0.5 0.15 calc(var(--h) + 45)));
}
.ctc-05__pill--who span {
font-family: ui-monospace,Menlo,monospace;
font-size: 12.5px;
}
.ctc-05__foot {
display: flex;
align-items: flex-start;
gap: 16px;
}
.ctc-05__reset {
flex: none;
min-height: 44px;
padding: 0 18px;
border-radius: 12px;
border: 1.5px solid var(--line);
background: oklch(0.995 0.002 250);
font: inherit;
font-size: 13.5px;
font-weight: 700;
color: var(--ink);
cursor: pointer;
transition: border-color .2s,translate .2s,box-shadow .2s;
}
.ctc-05__reset:hover,
.ctc-05__reset:focus-visible {
border-color: var(--acc);
color: var(--acc);
translate: 0 -1px;
box-shadow: 0 8px 16px -10px var(--acc);
}
.ctc-05__reset:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.ctc-05__foot p {
font-size: 12.5px;
line-height: 1.6;
color: var(--mut);
}
.ctc-05__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.01 250);
padding: 1px 5px;
border-radius: 4px;
color: var(--ink);
}
@container ctc05 (width < 520px) {
.ctc-05__foot {
flex-direction: column;
}
}
@media (prefers-reduced-motion: reduce) {
.ctc-05 * {
transition-duration: .01ms !important;
}
}.ctc-05,
.ctc-05 *,
.ctc-05 *::before,
.ctc-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ctc-05 {
--bg: oklch(0.965 0.008 250);
--ink: oklch(0.24 0.025 255);
--mut: oklch(0.5 0.02 255);
--line: oklch(0.88 0.012 250);
--acc: oklch(0.55 0.19 262);
--del: oklch(0.6 0.21 25);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
.ctc-05__stage {
width: 100%;
height: 100vh;
height: 100svh;
overflow-y: auto;
display: grid;
place-items: center;
padding: clamp(16px,4cqi,48px);
background: radial-gradient(75cqi 55cqi at 88% -12%,color-mix(in oklch,var(--acc) 13%,transparent),transparent 65%),var(--bg);
container: ctc05/inline-size;
border: 0;
}
.ctc-05__wrap {
width: min(680px,100%);
display: flex;
flex-direction: column;
gap: 16px;
}
.ctc-05__kicker {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--acc);
}
.ctc-05__head h1 {
font-size: clamp(24px,3.8cqi,38px);
font-weight: 800;
letter-spacing: -.03em;
margin: 8px 0 6px;
}
.ctc-05__panel {
background: oklch(0.995 0.002 250);
border: 1px solid var(--line);
border-radius: 18px;
padding: 16px 18px;
}
.ctc-05__lab {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.ctc-05__n {
display: inline-flex;
min-height: 22px;
align-items: center;
padding: 0 9px;
border-radius: 99px;
background: color-mix(in oklch,var(--acc) 13%,transparent);
color: var(--acc);
font-size: 11px;
font-weight: 800;
font-variant-numeric: tabular-nums;
letter-spacing: 0;
}
.ctc-05__row {
display: flex;
flex-wrap: wrap;
}
.ctc-05__row--skills {
counter-reset: ctc05n;
}
.ctc-05__row--skills .ctc-05__pill:not(:has(:checked)) {
counter-increment: ctc05n;
}
.ctc-05__n::after {
content: counter(ctc05n) " kept";
}
.ctc-05__pill {
display: inline-flex;
align-items: center;
gap: 9px;
min-height: 44px;
max-width: 320px;
padding: 0 9px 0 17px;
margin: 0 9px 9px 0;
border-radius: 99px;
border: 1.5px solid var(--line);
background: oklch(0.975 0.006 250);
font-size: 14px;
font-weight: 650;
white-space: nowrap;
overflow: hidden;
transition: max-width .38s,padding .38s,margin .38s,opacity .3s,scale .3s,border-color .2s,background .2s;
}
.ctc-05__pill:hover {
border-color: color-mix(in oklch,var(--acc) 40%,var(--line));
background: oklch(0.99 0.004 250);
}
.ctc-05__pill input {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 24px;
height: 24px;
border-radius: 50%;
border: 0;
background: color-mix(in oklch,var(--ink) 8%,transparent);
cursor: pointer;
transition: background .2s,rotate .25s;
outline-offset: 2px;
}
.ctc-05__pill input::before,
.ctc-05__pill input::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 1.8px;
border-radius: 2px;
background: var(--mut);
translate: -50% -50%;
transition: background .2s;
}
.ctc-05__pill input::before {
rotate: 45deg;
}
.ctc-05__pill input::after {
rotate: -45deg;
}
.ctc-05__pill input:hover,
.ctc-05__pill input:focus-visible {
background: color-mix(in oklch,var(--del) 16%,transparent);
rotate: 90deg;
}
.ctc-05__pill input:hover::before,
.ctc-05__pill input:hover::after,
.ctc-05__pill input:focus-visible::before,
.ctc-05__pill input:focus-visible::after {
background: var(--del);
}
.ctc-05__pill input:focus-visible {
outline: 2px solid var(--del);
}
.ctc-05__pill:has(:checked) {
max-width: 0;
padding-inline: 0;
margin: 0;
opacity: 0;
scale: .7;
pointer-events: none;
border-color: transparent;
}
.ctc-05__pill--who {
padding-left: 6px;
gap: 8px;
}
.ctc-05__pill--who i {
width: 30px;
height: 30px;
flex: none;
border-radius: 50%;
display: grid;
place-items: center;
font-style: normal;
font-size: 11px;
font-weight: 800;
color: oklch(0.99 0 0);
background: linear-gradient(140deg,oklch(0.68 0.13 var(--h)),oklch(0.5 0.15 calc(var(--h) + 45)));
}
.ctc-05__pill--who span {
font-family: ui-monospace,Menlo,monospace;
font-size: 12.5px;
}
.ctc-05__foot {
display: flex;
align-items: flex-start;
gap: 16px;
}
.ctc-05__reset {
flex: none;
min-height: 44px;
padding: 0 18px;
border-radius: 12px;
border: 1.5px solid var(--line);
background: oklch(0.995 0.002 250);
font: inherit;
font-size: 13.5px;
font-weight: 700;
color: var(--ink);
cursor: pointer;
transition: border-color .2s,translate .2s,box-shadow .2s;
}
.ctc-05__reset:hover,
.ctc-05__reset:focus-visible {
border-color: var(--acc);
color: var(--acc);
translate: 0 -1px;
box-shadow: 0 8px 16px -10px var(--acc);
}
.ctc-05__reset:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.ctc-05__foot p {
font-size: 12.5px;
line-height: 1.6;
color: var(--mut);
}
.ctc-05__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.01 250);
padding: 1px 5px;
border-radius: 4px;
color: var(--ink);
}
@container ctc05 (width < 520px) {
.ctc-05__foot {
flex-direction: column;
}
}
@media (prefers-reduced-motion: reduce) {
.ctc-05 * {
transition-duration: .01ms !important;
}
}Here's a working CSS Tags & Chip from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Deletable Pill Tag with Close Button
Source: https://codefronts.com/snippets/css-tags-chips/removable-pill/
Pills that actually delete — with zero JavaScript. The × is a real focusable control (a restyled checkbox), so clicking or pressing Space collapses the pill with a width-and-scale exit animation; a CSS counter live-decrements the total; and one <button type="reset"> resurrects everything because the group is a <form>. The anatomy is the part worth stealing: text region and delete control are separate hit targets, exactly like Gmail's recipient chips.
## HTML
```html
<section class="ctc-05" aria-label="Deletable pill tag demo">
<form class="ctc-05__stage">
<div class="ctc-05__wrap">
<header class="ctc-05__head">
<p class="ctc-05__kicker">Deletable pills · checkbox as close button</p>
<h1>Delete with ×. Undo with reset.</h1>
</header>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Skills <span class="ctc-05__n" aria-hidden="true"></span></p>
<div class="ctc-05__row ctc-05__row--skills">
<span class="ctc-05__pill"><span>Design systems</span><input type="checkbox" aria-label="Remove Design systems"></span>
<span class="ctc-05__pill"><span>Figma</span><input type="checkbox" aria-label="Remove Figma"></span>
<span class="ctc-05__pill"><span>CSS architecture</span><input type="checkbox" aria-label="Remove CSS architecture"></span>
<span class="ctc-05__pill"><span>Motion design</span><input type="checkbox" aria-label="Remove Motion design"></span>
<span class="ctc-05__pill"><span>Accessibility</span><input type="checkbox" aria-label="Remove Accessibility"></span>
<span class="ctc-05__pill"><span>Prototyping</span><input type="checkbox" aria-label="Remove Prototyping"></span>
<span class="ctc-05__pill"><span>User research</span><input type="checkbox" aria-label="Remove User research"></span>
</div>
</div>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Recipient variant — same anatomy, plus an initial block</p>
<div class="ctc-05__row">
<span class="ctc-05__pill ctc-05__pill--who" style="--h:250"><i>JR</i><span>jonas@relay.app</span><input type="checkbox" aria-label="Remove jonas@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:330"><i>MV</i><span>mara@relay.app</span><input type="checkbox" aria-label="Remove mara@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:150"><i>PA</i><span>priya@relay.app</span><input type="checkbox" aria-label="Remove priya@relay.app"></span>
</div>
</div>
<footer class="ctc-05__foot">
<button class="ctc-05__reset" type="reset">↺ Restore all</button>
<p>The × is the checkbox itself — <code>appearance:none</code>, drawn with two bars, focusable, Space-toggleable. Deletion is <code>.pill:has(:checked)</code> collapsing max-width, padding, margin and scale together.</p>
</footer>
</div>
</form>
</section>
```
## CSS
```css
.ctc-05,
.ctc-05 *,
.ctc-05 *::before,
.ctc-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ctc-05 {
--bg: oklch(0.965 0.008 250);
--ink: oklch(0.24 0.025 255);
--mut: oklch(0.5 0.02 255);
--line: oklch(0.88 0.012 250);
--acc: oklch(0.55 0.19 262);
--del: oklch(0.6 0.21 25);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
.ctc-05__stage {
width: 100%;
height: 100vh;
height: 100svh;
overflow-y: auto;
display: grid;
place-items: center;
padding: clamp(16px,4cqi,48px);
background: radial-gradient(75cqi 55cqi at 88% -12%,color-mix(in oklch,var(--acc) 13%,transparent),transparent 65%),var(--bg);
container: ctc05/inline-size;
border: 0;
}
.ctc-05__wrap {
width: min(680px,100%);
display: flex;
flex-direction: column;
gap: 16px;
}
.ctc-05__kicker {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--acc);
}
.ctc-05__head h1 {
font-size: clamp(24px,3.8cqi,38px);
font-weight: 800;
letter-spacing: -.03em;
margin: 8px 0 6px;
}
.ctc-05__panel {
background: oklch(0.995 0.002 250);
border: 1px solid var(--line);
border-radius: 18px;
padding: 16px 18px;
}
.ctc-05__lab {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.ctc-05__n {
display: inline-flex;
min-height: 22px;
align-items: center;
padding: 0 9px;
border-radius: 99px;
background: color-mix(in oklch,var(--acc) 13%,transparent);
color: var(--acc);
font-size: 11px;
font-weight: 800;
font-variant-numeric: tabular-nums;
letter-spacing: 0;
}
.ctc-05__row {
display: flex;
flex-wrap: wrap;
}
.ctc-05__row--skills {
counter-reset: ctc05n;
}
.ctc-05__row--skills .ctc-05__pill:not(:has(:checked)) {
counter-increment: ctc05n;
}
.ctc-05__n::after {
content: counter(ctc05n) " kept";
}
.ctc-05__pill {
display: inline-flex;
align-items: center;
gap: 9px;
min-height: 44px;
max-width: 320px;
padding: 0 9px 0 17px;
margin: 0 9px 9px 0;
border-radius: 99px;
border: 1.5px solid var(--line);
background: oklch(0.975 0.006 250);
font-size: 14px;
font-weight: 650;
white-space: nowrap;
overflow: hidden;
transition: max-width .38s,padding .38s,margin .38s,opacity .3s,scale .3s,border-color .2s,background .2s;
}
.ctc-05__pill:hover {
border-color: color-mix(in oklch,var(--acc) 40%,var(--line));
background: oklch(0.99 0.004 250);
}
.ctc-05__pill input {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 24px;
height: 24px;
border-radius: 50%;
border: 0;
background: color-mix(in oklch,var(--ink) 8%,transparent);
cursor: pointer;
transition: background .2s,rotate .25s;
outline-offset: 2px;
}
.ctc-05__pill input::before,
.ctc-05__pill input::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 1.8px;
border-radius: 2px;
background: var(--mut);
translate: -50% -50%;
transition: background .2s;
}
.ctc-05__pill input::before {
rotate: 45deg;
}
.ctc-05__pill input::after {
rotate: -45deg;
}
.ctc-05__pill input:hover,
.ctc-05__pill input:focus-visible {
background: color-mix(in oklch,var(--del) 16%,transparent);
rotate: 90deg;
}
.ctc-05__pill input:hover::before,
.ctc-05__pill input:hover::after,
.ctc-05__pill input:focus-visible::before,
.ctc-05__pill input:focus-visible::after {
background: var(--del);
}
.ctc-05__pill input:focus-visible {
outline: 2px solid var(--del);
}
.ctc-05__pill:has(:checked) {
max-width: 0;
padding-inline: 0;
margin: 0;
opacity: 0;
scale: .7;
pointer-events: none;
border-color: transparent;
}
.ctc-05__pill--who {
padding-left: 6px;
gap: 8px;
}
.ctc-05__pill--who i {
width: 30px;
height: 30px;
flex: none;
border-radius: 50%;
display: grid;
place-items: center;
font-style: normal;
font-size: 11px;
font-weight: 800;
color: oklch(0.99 0 0);
background: linear-gradient(140deg,oklch(0.68 0.13 var(--h)),oklch(0.5 0.15 calc(var(--h) + 45)));
}
.ctc-05__pill--who span {
font-family: ui-monospace,Menlo,monospace;
font-size: 12.5px;
}
.ctc-05__foot {
display: flex;
align-items: flex-start;
gap: 16px;
}
.ctc-05__reset {
flex: none;
min-height: 44px;
padding: 0 18px;
border-radius: 12px;
border: 1.5px solid var(--line);
background: oklch(0.995 0.002 250);
font: inherit;
font-size: 13.5px;
font-weight: 700;
color: var(--ink);
cursor: pointer;
transition: border-color .2s,translate .2s,box-shadow .2s;
}
.ctc-05__reset:hover,
.ctc-05__reset:focus-visible {
border-color: var(--acc);
color: var(--acc);
translate: 0 -1px;
box-shadow: 0 8px 16px -10px var(--acc);
}
.ctc-05__reset:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.ctc-05__foot p {
font-size: 12.5px;
line-height: 1.6;
color: var(--mut);
}
.ctc-05__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.01 250);
padding: 1px 5px;
border-radius: 4px;
color: var(--ink);
}
@container ctc05 (width < 520px) {
.ctc-05__foot {
flex-direction: column;
}
}
@media (prefers-reduced-motion: reduce) {
.ctc-05 * {
transition-duration: .01ms !important;
}
}
```Here's a working CSS Tags & Chip from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Deletable Pill Tag with Close Button
Source: https://codefronts.com/snippets/css-tags-chips/removable-pill/
Pills that actually delete — with zero JavaScript. The × is a real focusable control (a restyled checkbox), so clicking or pressing Space collapses the pill with a width-and-scale exit animation; a CSS counter live-decrements the total; and one <button type="reset"> resurrects everything because the group is a <form>. The anatomy is the part worth stealing: text region and delete control are separate hit targets, exactly like Gmail's recipient chips.
## HTML
```html
<section class="ctc-05" aria-label="Deletable pill tag demo">
<form class="ctc-05__stage">
<div class="ctc-05__wrap">
<header class="ctc-05__head">
<p class="ctc-05__kicker">Deletable pills · checkbox as close button</p>
<h1>Delete with ×. Undo with reset.</h1>
</header>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Skills <span class="ctc-05__n" aria-hidden="true"></span></p>
<div class="ctc-05__row ctc-05__row--skills">
<span class="ctc-05__pill"><span>Design systems</span><input type="checkbox" aria-label="Remove Design systems"></span>
<span class="ctc-05__pill"><span>Figma</span><input type="checkbox" aria-label="Remove Figma"></span>
<span class="ctc-05__pill"><span>CSS architecture</span><input type="checkbox" aria-label="Remove CSS architecture"></span>
<span class="ctc-05__pill"><span>Motion design</span><input type="checkbox" aria-label="Remove Motion design"></span>
<span class="ctc-05__pill"><span>Accessibility</span><input type="checkbox" aria-label="Remove Accessibility"></span>
<span class="ctc-05__pill"><span>Prototyping</span><input type="checkbox" aria-label="Remove Prototyping"></span>
<span class="ctc-05__pill"><span>User research</span><input type="checkbox" aria-label="Remove User research"></span>
</div>
</div>
<div class="ctc-05__panel">
<p class="ctc-05__lab">Recipient variant — same anatomy, plus an initial block</p>
<div class="ctc-05__row">
<span class="ctc-05__pill ctc-05__pill--who" style="--h:250"><i>JR</i><span>jonas@relay.app</span><input type="checkbox" aria-label="Remove jonas@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:330"><i>MV</i><span>mara@relay.app</span><input type="checkbox" aria-label="Remove mara@relay.app"></span>
<span class="ctc-05__pill ctc-05__pill--who" style="--h:150"><i>PA</i><span>priya@relay.app</span><input type="checkbox" aria-label="Remove priya@relay.app"></span>
</div>
</div>
<footer class="ctc-05__foot">
<button class="ctc-05__reset" type="reset">↺ Restore all</button>
<p>The × is the checkbox itself — <code>appearance:none</code>, drawn with two bars, focusable, Space-toggleable. Deletion is <code>.pill:has(:checked)</code> collapsing max-width, padding, margin and scale together.</p>
</footer>
</div>
</form>
</section>
```
## CSS
```css
.ctc-05,
.ctc-05 *,
.ctc-05 *::before,
.ctc-05 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ctc-05 {
--bg: oklch(0.965 0.008 250);
--ink: oklch(0.24 0.025 255);
--mut: oklch(0.5 0.02 255);
--line: oklch(0.88 0.012 250);
--acc: oklch(0.55 0.19 262);
--del: oklch(0.6 0.21 25);
font-family: 'Segoe UI',system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
.ctc-05__stage {
width: 100%;
height: 100vh;
height: 100svh;
overflow-y: auto;
display: grid;
place-items: center;
padding: clamp(16px,4cqi,48px);
background: radial-gradient(75cqi 55cqi at 88% -12%,color-mix(in oklch,var(--acc) 13%,transparent),transparent 65%),var(--bg);
container: ctc05/inline-size;
border: 0;
}
.ctc-05__wrap {
width: min(680px,100%);
display: flex;
flex-direction: column;
gap: 16px;
}
.ctc-05__kicker {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .16em;
text-transform: uppercase;
color: var(--acc);
}
.ctc-05__head h1 {
font-size: clamp(24px,3.8cqi,38px);
font-weight: 800;
letter-spacing: -.03em;
margin: 8px 0 6px;
}
.ctc-05__panel {
background: oklch(0.995 0.002 250);
border: 1px solid var(--line);
border-radius: 18px;
padding: 16px 18px;
}
.ctc-05__lab {
font-size: 11.5px;
font-weight: 800;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.ctc-05__n {
display: inline-flex;
min-height: 22px;
align-items: center;
padding: 0 9px;
border-radius: 99px;
background: color-mix(in oklch,var(--acc) 13%,transparent);
color: var(--acc);
font-size: 11px;
font-weight: 800;
font-variant-numeric: tabular-nums;
letter-spacing: 0;
}
.ctc-05__row {
display: flex;
flex-wrap: wrap;
}
.ctc-05__row--skills {
counter-reset: ctc05n;
}
.ctc-05__row--skills .ctc-05__pill:not(:has(:checked)) {
counter-increment: ctc05n;
}
.ctc-05__n::after {
content: counter(ctc05n) " kept";
}
.ctc-05__pill {
display: inline-flex;
align-items: center;
gap: 9px;
min-height: 44px;
max-width: 320px;
padding: 0 9px 0 17px;
margin: 0 9px 9px 0;
border-radius: 99px;
border: 1.5px solid var(--line);
background: oklch(0.975 0.006 250);
font-size: 14px;
font-weight: 650;
white-space: nowrap;
overflow: hidden;
transition: max-width .38s,padding .38s,margin .38s,opacity .3s,scale .3s,border-color .2s,background .2s;
}
.ctc-05__pill:hover {
border-color: color-mix(in oklch,var(--acc) 40%,var(--line));
background: oklch(0.99 0.004 250);
}
.ctc-05__pill input {
appearance: none;
-webkit-appearance: none;
position: relative;
flex: none;
width: 24px;
height: 24px;
border-radius: 50%;
border: 0;
background: color-mix(in oklch,var(--ink) 8%,transparent);
cursor: pointer;
transition: background .2s,rotate .25s;
outline-offset: 2px;
}
.ctc-05__pill input::before,
.ctc-05__pill input::after {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 1.8px;
border-radius: 2px;
background: var(--mut);
translate: -50% -50%;
transition: background .2s;
}
.ctc-05__pill input::before {
rotate: 45deg;
}
.ctc-05__pill input::after {
rotate: -45deg;
}
.ctc-05__pill input:hover,
.ctc-05__pill input:focus-visible {
background: color-mix(in oklch,var(--del) 16%,transparent);
rotate: 90deg;
}
.ctc-05__pill input:hover::before,
.ctc-05__pill input:hover::after,
.ctc-05__pill input:focus-visible::before,
.ctc-05__pill input:focus-visible::after {
background: var(--del);
}
.ctc-05__pill input:focus-visible {
outline: 2px solid var(--del);
}
.ctc-05__pill:has(:checked) {
max-width: 0;
padding-inline: 0;
margin: 0;
opacity: 0;
scale: .7;
pointer-events: none;
border-color: transparent;
}
.ctc-05__pill--who {
padding-left: 6px;
gap: 8px;
}
.ctc-05__pill--who i {
width: 30px;
height: 30px;
flex: none;
border-radius: 50%;
display: grid;
place-items: center;
font-style: normal;
font-size: 11px;
font-weight: 800;
color: oklch(0.99 0 0);
background: linear-gradient(140deg,oklch(0.68 0.13 var(--h)),oklch(0.5 0.15 calc(var(--h) + 45)));
}
.ctc-05__pill--who span {
font-family: ui-monospace,Menlo,monospace;
font-size: 12.5px;
}
.ctc-05__foot {
display: flex;
align-items: flex-start;
gap: 16px;
}
.ctc-05__reset {
flex: none;
min-height: 44px;
padding: 0 18px;
border-radius: 12px;
border: 1.5px solid var(--line);
background: oklch(0.995 0.002 250);
font: inherit;
font-size: 13.5px;
font-weight: 700;
color: var(--ink);
cursor: pointer;
transition: border-color .2s,translate .2s,box-shadow .2s;
}
.ctc-05__reset:hover,
.ctc-05__reset:focus-visible {
border-color: var(--acc);
color: var(--acc);
translate: 0 -1px;
box-shadow: 0 8px 16px -10px var(--acc);
}
.ctc-05__reset:focus-visible {
outline: 2px solid var(--acc);
outline-offset: 2px;
}
.ctc-05__foot p {
font-size: 12.5px;
line-height: 1.6;
color: var(--mut);
}
.ctc-05__foot code {
font-family: ui-monospace,Menlo,monospace;
font-size: .9em;
background: oklch(0.92 0.01 250);
padding: 1px 5px;
border-radius: 4px;
color: var(--ink);
}
@container ctc05 (width < 520px) {
.ctc-05__foot {
flex-direction: column;
}
}
@media (prefers-reduced-motion: reduce) {
.ctc-05 * {
transition-duration: .01ms !important;
}
}
```How this works
The close button IS the checkbox. Instead of hiding an input and styling a label, the input itself gets appearance:none and is drawn as the × circle — which means the delete control is natively focusable, toggleable with Space, and carries its own aria-label:
.pill input{ appearance:none; width:22px; height:22px;
border-radius:50%; cursor:pointer } /* the × is drawn by ::before/::after bars */
.pill:has(:checked){ max-width:0; padding-inline:0;
margin:0; opacity:0; scale:.7; pointer-events:none }Deletion is the :has(:checked) state collapsing the pill. The exit animates max-width from a generous cap to 0 alongside padding, margin, opacity and scale — that combination is what makes neighboring pills slide over smoothly instead of snapping. The container deliberately uses margins instead of flex gap, because a zero-width flex item still contributes its gap; margins collapse to nothing with the pill.
The live count is a CSS counter that only increments on pills not deleted — .pill:not(:has(:checked)){ counter-increment: ctc05n } — rendered by an ::after on the summary line. And because everything is checkbox state inside a <form>, "Restore all" is a bare type="reset" button: the browser unchecks every ×, and the same transitions play forward.
Make it yours
- Exit speed/feel: one
transitionline on.ctc-05__pill— 350ms with ease works for chips; go 500ms + a springy bezier for playful UIs. - Max-width cap: 320px covers most tag text; if you allow long tags, raise it (the cap only exists so the width animation has a start value).
- Confirm-style delete: move the collapse rules from
:has(:checked)to:has(:checked):hover's inverse — or keep a two-step pattern by styling:checkedfirst as an “armed” red state and deleting on a second control. - Avatar chips: the recipient variant just drops an
<i>initial block before the text — the delete anatomy is identical.
Gotchas — read before shipping
- This is visual deletion: the checkbox still posts its state. In a real form, name the checkboxes (e.g. remove[]) and read them server-side, or genuinely remove nodes with JS when it matters.
- Flex gap does not collapse with a 0-width item — use margins on pills (as here) or the deleted pill leaves a ghost gap behind.
- Put the aria-label on the input ("Remove Figma"), never on the pill wrapper — the wrapper is not the interactive element.
- max-width transitions animate layout — fine for a row of chips, but do not run 200 simultaneously; stagger with transition-delay or cap the visible set.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 121+ | 111+ |
The collapse state needs :has() (Firefox 121+). appearance:none checkboxes and max-width transitions are ancient. Without :has(), the × still checks (turns the armed color) but pills stay — degraded, not broken; oklch tokens set the styling floor.