A small pill that is a filter or a removable value.
On this page
A chip is a small pill that is a choice or a value. Its ends are true half circles, which tells it apart from a badge: a badge describes, a chip can be acted on. As a filter, a chip is a <label> around a native checkbox or radio, raised at rest and filled with ink when chosen, the way a checkbox fills.
With radios that share a name, chips are a single choice, and the arrow keys move between them. Use this for a short set that changes a view at once; for a value in a form, a segmented control reads as one control.
Without an input a chip is a value: a recipient, a tag, an applied filter. It rests in a chip tone on one contour. chip-remove is a round button at its end; give it a name that includes the value. Put icon on a leading icon.
The input inside a filter chip covers it invisibly, so the label is the target and the input keeps the state, the keys and the form value. Group filter chips in a <fieldset> with a <legend>, or a role="radiogroup" with a label.
The remove button's target reaches past its 20px glyph without moving it: 28px, and 36px on touch screens, where a filter chip grows to 44px like every other target.
A chosen chip is ink on moonstone and pearl on obsidian, with no hue, so it does not depend on color vision.
/* * Chip: a small pill that is a choice or a value. * As a label around a checkbox or a radio it is a filter: raised at rest, filled with ink when chosen, * the way a checkbox fills. As a plain element it is a value that can carry a remove button. * A chip is 28px tall; its ends are true half circles, which tells it apart from a badge. */@layer components {.chip{--chip-height:1.75rem;--chip-padding-x:.625rem;--icon-size:.875rem;--icon-offset:-.0625rem;position:relative;display:inline-flex;flex-shrink:0;align-items:center;gap:.375rem;min-height:var(--chip-height);margin:0;padding:0var(--chip-padding-x);border:0;border-radius:999px;background:var(--color-surface-chip);color:var(--color-text-strong);box-shadow:inset000.5pxvar(--color-line-contour);font:var(--font-weight-control).78125rem/1var(--font-family-sans);font-feature-settings:inherit;white-space:nowrap;vertical-align:middle;-webkit-tap-highlight-color:transparent;/* A chip that holds a .chip-input is a control: a small raised sheet that lifts under the pointer. */&:has(.chip-input){--chip-lift:var(--lift);@apply--surface-sheet;box-shadow:var(--shadow-raised);user-select:none;-webkit-user-select:none;cursor:pointer;touch-action:manipulation;transition-property: box-shadow, translate,color;transition-duration:var(--duration-quick);transition-timing-function:var(--easing-glide);@media(hover:hover){&:hover:not(:has(.chip-input:disabled)){translate:0calc(-1*var(--chip-lift));box-shadow:var(--shadow-raised-hover);}}&:active:not(:has(.chip-input:disabled)){translate:0var(--chip-lift);transition-duration:var(--duration-press);}}/* Chosen: ink, with the same line of light a checked checkbox has. */&:has(.chip-input:checked){background:var(--color-surface-inverse);color:var(--color-text-inverse);box-shadow:inset0.5px0var(--color-ink-highlight),000.5pxvar(--color-ink-edge),01px2px-1pxvar(--color-shade-1),02px4px-2pxvar(--color-shade-2);@media(hover:hover){&:hover:not(:has(.chip-input:disabled)){box-shadow:inset0.5px0var(--color-ink-highlight),000.5pxvar(--color-ink-edge),01px2px-1pxvar(--color-shade-1),03px6px-3pxvar(--color-shade-2),06px12px-6pxvar(--color-shade-3);}}}&:has(.chip-input:focus-visible){@apply--focus-ring;}&:has(.chip-input:disabled){background:var(--color-surface-inset);color:var(--color-text-disabled);box-shadow:var(--shadow-flat);cursor:not-allowed;}/* A remove button stands as far from the pill's end as from its top and bottom, so the two circles are concentric. */&:has(.chip-remove){padding-inline-end:calc((var(--chip-height)-1.25rem)/2);}/* On touch a filter is 44px, as every other target is. */@media(pointer:coarse){&:has(.chip-input){min-height:2.75rem;padding-inline:1rem;}}@media(prefers-reduced-motion:reduce){&:has(.chip-input){--chip-lift:0px;}}@media(forced-colors:active){outline:1pxsolid CanvasText;outline-offset:-1px;&:has(.chip-input:checked){background: Highlight;color: HighlightText;forced-color-adjust:none;}}}/* The checkbox or radio inside a chip covers it invisibly: the label is the target, the input keeps the state. */.chip-input{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;border:0;border-radius:inherit;opacity:0;appearance:none;cursor:inherit;}/* Removes the value; give it an accessible name that includes the value. */.chip-remove{position:relative;display:inline-grid;flex:none;place-items:center;width:1.25rem;height:1.25rem;margin:0;padding:0;border:0;border-radius:999px;background:transparent;color:var(--color-text-muted);appearance:none;cursor:pointer;touch-action:manipulation;&::before{content:'';width:.75rem;height:.75rem;background:currentColor;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M4.5 4.5l7 7M11.5 4.5l-7 7'/%3E%3C/svg%3E")center/containno-repeat;}/* The target reaches past the glyph without moving it: 28px, and 36px on touch. */&::after{content:'';position:absolute;inset:-.25rem;@media(pointer:coarse){inset:-.5rem;}}@media(hover:hover){&:hover{background:var(--color-line-contour);color:var(--color-text-strong);}}/* Pressed: a firmer tone than the pointer's, so a tap is answered where there is no pointer. */&:active{background:var(--color-line-strong);color:var(--color-text-strong);}&:focus-visible{@apply--focus-ring;outline-offset:0;}@media(forced-colors:active){&::before{background: ButtonText;}}}}