Tag
Tag — a chip standing for a value the user put there and can take away: a filter that has been applied, a recipient in a compose field, a label on a ticket.
Examples
<ul class="tag-list">
<li>
<span class="tag">
<span class="tag-label">Design</span>
<button class="tag-remove" type="button">
<svg class="icon" aria-hidden="true"><use href="#icon-x"></use></svg>
<span class="sr-only">Remove Design</span>
</button>
</span>
</li>
<li>
<span class="tag">
<span class="tag-label">Research</span>
<button class="tag-remove" type="button">
<svg class="icon" aria-hidden="true"><use href="#icon-x"></use></svg>
<span class="sr-only">Remove Research</span>
</button>
</span>
</li>
</ul>The remove control is a real <button> with a real name — "Remove Design", not "×".
A badge is output the user cannot act on; a tag is input they can, and that difference is a focusable control and a keyboard path, not a coat of paint.
Design
<span class="tag"><span class="tag-label">Design</span></span>A tag that cannot be removed needs no button.
Tokens 18
Level 2, declared on .tag itself. Set any of them on that selector to restyle this component without touching the skin.
| Token | Default |
|---|---|
| --tag-list-gap | var(--space-2) |
| --tag-remove-bg | transparent |
| --tag-remove-color | var(--color-on-surface-muted) |
| --tag-remove-size | 1.25rem |
| --tag-remove-hover-bg | var(--color-surface-sunken) |
| --tag-remove-hover-color | var(--color-on-surface) |
| --tag-bg | var(--color-surface-sunken) |
| --tag-border-color | var(--color-border) |
| --tag-border-width | var(--border-width) |
| --tag-color | var(--color-on-surface) |
| --tag-font-family | var(--font-secondary) |
| --tag-font-size | var(--font-size-xs) |
| --tag-font-weight | var(--font-weight-medium) |
| --tag-gap | var(--space-1) |
| --tag-min-size | 1.75rem |
| --tag-padding-block | var(--space-1) |
| --tag-padding-inline | var(--space-2) |
| --tag-radius | var(--radius-field) |
Variants and states
Variants
.tag-lg.tag-round.tag-sm
Inside it
.tag-remove.tag-list.tag-label
State it reads
Read from the platform, never mirrored into a class that could disagree with it.
:disabled:focus:hover
Before you ship it
What you have to do 1 requirements
- Name every remove button after its tag. "Remove Design". This is the one thing in the component nothing can supply and nothing can detect the absence of, and it is why the icon is
aria-hiddenand the name is a.sr-onlychild rather than anaria-label— you can see it in the markup and notice when it is missing. Move focus before removing the node. See above. Use a list when there is more than one tag.<ul class="tag-list">makes a screen reader announce "list, 5 items", which is how someone knows how many filters are on without reading all of them.
src/css/components/tag.css · npx mostlycss add tag