Chip
Compact 24px pill for selection and input, built on native form controls with zero JavaScript — the Lozenge take on Material's chip family. Three recipes share the .chip skin: choice chips (single-select) are a <label class="chip chip-choice"> wrapping a hidden radio; filter chips (multi-select) are the same with a checkbox and grow a ✓ when checked; input chips are a plain <span class="chip"> with a .chip-remove button. A bare <span class="chip"> is a static pill (see also the squarer .tag).
Root: .chip on <span>, <label>
Examples
<span class="chip">design</span>
<label class="chip chip-choice"><input type="radio" name="priority" checked><span>Low</span></label>
<label class="chip chip-filter"><input type="checkbox"><span>Bug</span></label>
<span class="chip">frontend<button class="chip-remove" aria-label="Remove frontend">×</button></span>
Contract
Variants & modifiers
| Class | Axis | Rules |
|---|---|---|
chip-choice | role | optional · exclusive |
chip-filter | role | optional · exclusive |
Structure
| Selector | Required | Description |
|---|---|---|
input[type=radio] | optional | Choice chips only: visually-hidden radio as the first child of the <label class="chip chip-choice">. All chips in one choice group share a name; :checked relays selected styling to the label via :has(). |
input[type=checkbox] | optional | Filter chips only: visually-hidden checkbox as the first child of the <label class="chip chip-filter">. |
span | optional | Selection chips (choice/filter): the visible label text must sit in a <span> immediately following the input — the ✓ indicator targets input:checked + span::before. |
button.chip-remove | optional | Input chips: remove button rendered after the label text; danger colors on hover. Must be a <button> for keyboard operability. Do not combine with chip-choice/chip-filter (a button inside a label would steal the label's activation). |
Accessibility
| On | Attribute | Level | When |
|---|---|---|---|
.chip-remove | aria-label | required |
Selection chips ride on native radio/checkbox semantics: Tab reaches the group, arrow keys move within a radio group, Space toggles a checkbox — add no ARIA roles on top. The hidden input's :focus-visible relays a focus ring to the label via :has(). Give each choice group a distinct radio name. Name what .chip-remove removes (aria-label="Remove frontend", not "Remove"). Disable a selection chip by disabling its input, not the label.
Nesting
Allowed in:
filter rowstoolbarsformsissue detail headerscard footers
Never inside (or containing):
.chip.btn