Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

Components

Select

Leverages the List component to provide markup for the Select popover.

Full support Supported since v135. Partial support Missing: customizable-select, overlay. Partial support Missing: customizable-select, overlay.

Variants

<label class="select">
<span class="label">Label</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Outlined (default)</option>
<option>Option Two</option>
<option>Option Three</option>
</div>
</select>
</span>
</label>
<label class="select filled">
<span class="label">Label</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Filled</option>
<option>Option Two</option>
<option>Option Three</option>
</div>
</select>
</span>
</label>

End text

.end-text: end text element

<label class="select">
<span class="label">Label</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Outlined (default)</option>
<option>Option Two</option>
<option>Option Three</option>
</div>
</select>
</span>
<span class="end-text">Supporting text</span>
</label>
<label class="select filled">
<span class="label">Label</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Filled</option>
<option>Option Two</option>
<option>Option Three</option>
</div>
</select>
</span>
<span class="end-text">Supporting text</span>
</label>

Affix

Add a .prefix or .suffix element inside .field to affix content alongside the select.

<label class="select">
<span class="label">Currency</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">-</option>
<option>EUR</option>
<option>EUR</option>
<option>SEK</option>
</div>
</select>
<span class="prefix">¢</span>
</span>
</label>
<label class="select">
<span class="label">Country</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">-</option>
<option>Sweden</option>
<option>Norway</option>
<option>Denmark</option>
</div>
</select>
<span class="prefix">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<path d="M2 12h20"></path>
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
</svg>
</span>
</span>
</label>

Validation

  • Add [required] to the <select> element to toggle required styles.
  • Add the data-invalid attribute on the root element to toggle error styles. Make use of the end text to give extra feedback on the error.
<label class="select">
<span class="label">Label</span>
<span class="field">
<select required>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Pick me!</option>
<option>No me!!</option>
<option>Come on!</option>
</div>
</select>
</span>
</label>
<label class="select filled">
<span class="label">Label</span>
<span class="field">
<select required>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Pick me!</option>
<option>No me!!</option>
<option>Come on!</option>
</div>
</select>
</span>
</label>
<label class="select" data-invalid>
<span class="label">Label</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option selected>Wrong option</option>
<option>Also wrong!</option>
<option>Nothing's right!</option>
</div>
</select>
</span>
<span class="end-text">Supporting text</span>
</label>
<label class="select filled" data-invalid>
<span class="label">Label</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option selected>Wrong option</option>
<option>Also wrong!</option>
<option>Nothing's right!</option>
</div>
</select>
</span>
<span class="end-text">Supporting text</span>
</label>

Spread

Add the .spread class to display the label and description on the left with the select on the right. The layout collapses to a column on narrow containers.

<label class="select spread">
<span class="label">Country</span>
<span class="start-text">Select your country of residence</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">Select a country</option>
<option>Denmark</option>
<option>Finland</option>
<option>Iceland</option>
<option>Norway</option>
<option>Sweden</option>
</div>
</select>
</span>
</label>
<label class="select spread filled">
<span class="label">Language</span>
<span class="start-text">Choose your preferred language</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">Select a language</option>
<option>Danish</option>
<option>Finnish</option>
<option>Icelandic</option>
<option>Norwegian</option>
<option>Swedish</option>
</div>
</select>
</span>
<span class="end-text">This affects UI translations</span>
</label>
<label class="select spread">
<span class="label">Required</span>
<span class="start-text">You must select an option</span>
<span class="field">
<select required>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">Select an option</option>
<option>Option 1</option>
<option>Option 2</option>
</div>
</select>
</span>
</label>
<label class="select spread">
<span class="label">Disabled</span>
<span class="start-text">This select is disabled</span>
<span class="field">
<select disabled>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Option 1</option>
</div>
</select>
</span>
</label>
<label class="select spread" data-invalid>
<span class="label">Invalid Select</span>
<span class="start-text">This select has an error</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Option 1</option>
</div>
</select>
</span>
<span class="end-text">Please select a valid option.</span>
</label>
<label class="select spread">
<span class="label">Currency</span>
<span class="start-text">Used for billing</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">-</option>
<option>EUR</option>
<option>EUR</option>
<option>SEK</option>
</div>
</select>
<span class="prefix">¢</span>
</span>
</label>
<label class="select spread filled">
<span class="label">Region</span>
<span class="start-text">Affects data residency and latency</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option value="">-</option>
<option>eu-north-1</option>
<option>us-east-1</option>
<option>ap-southeast-1</option>
</div>
</select>
<span class="prefix">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"></circle>
<path d="M2 12h20"></path>
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
</svg>
</span>
</span>
<span class="end-text">Cannot be changed after deploy</span>
</label>

Sizes

<label class="select small">
<span class="label">Small</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Small</option>
<option>Option Two</option>
<option>Option Three</option>
</div>
</select>
</span>
</label>
<label class="select">
<span class="label">Default</span>
<span class="field">
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<div class="list">
<option>Default</option>
<option>Option Two</option>
<option>Option Three</option>
</div>
</select>
</span>
</label>

Classic select

Bog-standard native HTML <select> without customized option list.

<label class="select">
<span class="label">Label</span>
<span class="field">
<select>
<option value="">-</option>
<option>Option 1</option>
<option>Option 2</option>
</select>
</span>
</label>
<label class="select filled">
<span class="label">Label</span>
<span class="field">
<select>
<option value="">-</option>
<option>Option 1</option>
<option>Option 2</option>
</select>
</span>
</label>

Anatomy

  1. Select container: <select>
  2. Select button: <button>
  3. Select button selected option: <selectedcontent>
  4. Select button arrow
  5. Popover list: .list
  6. List option/s: <option>
  7. List option group/s (optional): <optgroup>
<div class="anatomy"> <div class="select"> <div> <button class="anatomy"> <selectedcontent> </button> <div class="list"> <option>Option One</option> </div> </div> </div> <div class="list"> <option selected>Option One</option> <option>Option Two</option> <option>Option Three</option> </div> </div>

API

Type Modifiers Default Description
Children .label, .start-text, .field, .end-text - Direct children of the root element.
Field children <select>, .prefix, .suffix, .header, .footer - Children of .field. The <select> comes first, then optional affixes.
Layout .spread, default - The layout of the component. .spread pushes label and description to the left and select to the right.
Sizes .small - The size of the element.
Variants default, .filled - The variant to use.
Validation [data-invalid] - Add the data-invalid attribute to the root element to show error styles.

Classic Select API

Type Modifiers Default Description
Sizes .small - The size of the element.
Variants default, .filled - The variant to use.

Browser support

Full support Supported since v135. Partial support Missing: customizable-select, overlay. Partial support Missing: customizable-select, overlay.

See also the full browser support guide.

Installation

Dependencies

@layer components.extended {
/*
- Common styling for input, textarea and select
- Form related styles such as: label, supporting text, error handling
*/
:where(.text-field, .textarea, .select) {
--_accent-color: var(--primary);
--_bg-color: var(--surface-default);
--_border-color: var(--field-border-color);
--_field-padding-block: var(--size-2);
--_field-padding-inline: var(--size-2);
--_filled-border-color: var(--text-primary);
--_height: var(--field-size);
--_label-color: var(--text-muted);
--_end-text-color: var(--text-muted);
display: grid;
gap: var(--size-1) 0;
position: relative;
/* Field - the actual input with a border around it */
.field {
background-color: var(--_bg-color);
border: var(--field-border-width) solid var(--_border-color);
border-radius: var(--field-border-radius);
display: grid;
grid-column: 1/-1;
grid-row: 2;
grid-template-columns: auto 1fr auto;
grid-template-areas:
"header header header"
"prefix input suffix"
"footer footer footer";
min-block-size: var(--_height);
@media (prefers-reduced-motion: no-preference) {
transition: border-color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
}
:where(.field) :where(input, textarea, select) {
background: transparent;
border: 0;
color: var(--text-primary);
font-family: var(--font-sans);
font-size: var(--font-size-1);
grid-area: input;
inline-size: 100%;
line-height: var(--font-lineheight-1);
min-inline-size: 0;
padding: var(--_field-padding-block) var(--_field-padding-inline);
&:focus,
&:focus-visible {
outline: 0;
}
}
/* Affixes */
.prefix,
.suffix {
align-items: center;
color: var(--_label-color);
display: inline-flex;
padding-inline: var(--_field-padding-inline);
white-space: nowrap;
}
.prefix {
grid-area: prefix;
}
.suffix {
grid-area: suffix;
}
.header,
.footer {
align-items: center;
color: var(--_label-color);
display: flex;
font-size: var(--font-size-0);
gap: var(--size-2);
padding: var(--size-1) var(--_field-padding-inline);
}
.header {
border-block-end: 1px solid var(--_border-color);
grid-area: header;
}
.footer {
border-block-start: 1px solid var(--_border-color);
grid-area: footer;
}
/* Remove padding on the input when affixes are next to it */
.field:has(> .prefix) :where(input, textarea, select) {
padding-inline-start: 0;
}
.field:has(> .suffix) :where(input, textarea, select) {
padding-inline-end: 0;
}
/* Textarea - keep affix aligned with the first line */
&.textarea .field {
.prefix,
.suffix {
align-self: start;
padding-block: var(--_field-padding-block);
}
}
/* Required/Invalid */
&:has(:invalid) {
.label:after {
color: var(--red);
content: "*";
margin: -0.25em auto auto 0.25em;
}
}
/* File */
&:has(input[type="file"]) {
cursor: pointer;
input {
align-self: flex-start;
block-size: var(--_height);
box-shadow: none;
color: var(--text-primary);
cursor: inherit;
max-inline-size: 100%;
padding: 0;
transition: font-size 0.2s var(--ease-3);
&::-webkit-file-upload-button,
&::file-selector-button {
background-color: var(--surface-tonal);
block-size: calc(100% - var(--size-2) * 2);
border: none;
border-radius: var(--field-border-radius);
cursor: pointer;
margin-block-start: var(--size-2);
margin-inline-end: 1ex;
margin-inline-start: var(--size-2);
}
}
/* Variants */
&.filled {
input {
&::-webkit-file-upload-button,
&::file-selector-button {
background-color: var(--surface-default);
block-size: calc(100% - var(--size-2) * 2);
border-radius: var(--field-border-radius);
cursor: pointer;
margin-block-start: var(--size-2);
}
}
}
/* Sizes */
&.small {
input {
font-size: var(--font-size-05);
&::-webkit-file-upload-button,
&::file-selector-button {
block-size: calc(100% - var(--size-2));
margin-block-start: var(--size-1);
}
}
}
}
/* Autosuggest */
&:has(input[list]) {
.label {
/* Make sure chevron is visible */
inline-size: calc(100% - var(--size-6));
}
}
/* Select */
&:has(select) {
.label {
/* Make sure chevron is visible */
inline-size: calc(100% - var(--size-6));
}
}
/* Customizable Select */
&:has(select button) {
select {
padding: 0;
button {
outline: 0;
padding: var(--_field-padding-block) var(--size-8) var(--_field-padding-block) var(--_field-padding-inline);
}
}
}
/* Non-customizable Select */
&:has(select):not(:has(button)) {
select {
padding: var(--_field-padding-block) var(--size-8) var(--_field-padding-block) var(--_field-padding-inline);
}
}
/* Input - color */
&:has(input[type="color"]) {
.field {
block-size: var(--_height);
inline-size: var(--_height);
min-block-size: 0;
overflow: hidden;
}
input {
appearance: none;
background: none;
block-size: var(--_height);
inline-size: var(--_height);
overflow: hidden;
padding: 0;
&::-webkit-color-swatch {
border: none;
}
&::-webkit-color-swatch-wrapper {
padding: 0;
}
}
}
/* Element states */
&:hover {
&:not([data-invalid]) {
.field {
border-color: var(--text-primary);
}
}
}
&:focus-within {
.field {
border-color: var(--_accent-color);
outline-offset: -2px;
}
}
/* Label */
.label {
color: var(--text-primary);
font-size: var(--font-size-05);
font-weight: 600;
grid-column: 1/-1;
grid-row: 1;
padding-inline: 0 1ex;
}
/* End text */
:where(.end-text) {
color: var(--_end-text-color);
font-size: var(--font-size-0);
grid-column: 1/-1;
grid-row: 3;
line-height: 1.5;
}
/* Auto-fit */
&.auto-fit {
inline-size: auto;
.field {
inline-size: auto;
}
:where(& input, & textarea) {
field-sizing: content;
inline-size: auto;
min-inline-size: 25ch;
}
}
/* Validation */
&[data-invalid],
&:has(:user-invalid) {
--_accent-color: var(--color-9);
--_border-color: var(--color-9);
--_filled-border-color: var(--color-9);
--_label-color: var(--color-9);
--_end-text-color: var(--color-9);
}
/*
* Variant: Filled
*/
&.filled {
--_bg-color: var(--surface-tonal);
&:not(:has([disabled], :has(input[type="color"]))) {
/* Hover */
&:hover {
--_bg-color: light-dark(oklch(from var(--surface-tonal) calc(l * 0.93) c h),
oklch(from var(--surface-tonal) calc(l * 1.1) c h));
}
}
}
/* Disabled */
&:where(:has([disabled])) {
cursor: not-allowed;
opacity: 0.64;
user-select: none;
&::before {
display: none;
}
.field {
cursor: not-allowed;
}
:where(input, textarea, select) {
cursor: not-allowed;
* {
pointer-events: none;
}
}
.label,
.start-text,
.end-text {
cursor: not-allowed;
}
}
/* Read-only */
&:where(:has([readonly])) {
&::before {
display: none;
}
:where(input, textarea, select) {
cursor: not-allowed;
* {
pointer-events: none;
}
}
}
/* Sizes */
&.small {
--_field-padding-block: var(--size-2);
--_height: var(--field-size-small);
&:has(input[type="color"]) {
.label {
line-height: 1.5;
}
}
}
/* Orientation */
&.spread {
align-items: start;
column-gap: var(--size-4);
container-type: inline-size;
grid-template-columns: 1fr auto;
.label {
font-weight: 600;
grid-column: 1;
grid-row: 1;
}
.start-text {
color: var(--_end-text-color);
font-size: var(--font-size-0);
grid-column: 1;
grid-row: 2;
line-height: 1.5;
}
.field {
align-self: start;
grid-column: 2;
grid-row: 1 / span 2;
}
.field:has(textarea) {
grid-row: 1 / span 3;
+.end-text {
grid-row: 4;
}
}
:where(textarea) {
min-inline-size: 30ch;
}
:where(.end-text) {
grid-column: 2;
text-align: end;
}
/* Collapse to column on narrow containers */
@container (width < 400px) {
column-gap: 0;
grid-template-columns: 1fr;
.label {
grid-column: 1;
grid-row: 1;
}
.start-text {
grid-column: 1;
grid-row: 2;
}
.field,
.field:has(textarea) {
grid-column: 1;
grid-row: 3;
}
:where(.end-text) {
grid-column: 1;
grid-row: 4;
text-align: start;
}
}
}
}
}
@layer components.extended {
:where(.select select) {
position: relative;
/* Default arrow */
&::picker-icon {
block-size: 0;
border-block-start: 5px solid;
border-inline: 5px solid transparent;
color: currentColor;
content: "";
inline-size: 0;
inset: 50% var(--size-3) auto auto;
pointer-events: none;
position: absolute;
translate: 0 -50%;
}
&:open {
&::picker-icon {
rotate: 180deg;
}
}
/* Select popover */
&::picker(select) {
/* Animation on-stage styles */
border: 0;
box-shadow: var(--shadow-2);
opacity: 1;
padding: 0;
scale: 1;
/* Animation starting styles */
@starting-style {
opacity: 0;
transform: scale(0.9);
}
@media (prefers-reduced-motion: no-preference) {
transition: display 0.2s allow-discrete, opacity 0.2s var(--ease-3),
overlay 0.2s allow-discrete, scale 0.2s var(--ease-3);
}
}
/* Animation off-stage styles */
&:not(:open)::picker(select) {
opacity: 0;
scale: 0.9;
}
button {
align-items: center;
background-color: transparent;
display: flex;
inline-size: 100%;
margin: 0;
position: relative;
selectedcontent {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.list {
--_bg-color: var(--surface-filled);
border: var(--field-border-width) solid var(--field-border-color);
border-radius: var(--field-border-radius);
/* Groups */
[role="group"] {
label {
background-color: light-dark(var(--gray-3), var(--gray-13));
color: light-dark(oklch(from var(--text-primary) calc(l * 0.75) c h),
oklch(from var(--text-primary) calc(l * 1.25) c h));
font-weight: 500;
overflow: hidden;
padding-inline: var(--size-2);
text-overflow: ellipsis;
white-space: nowrap;
}
&:not(:first-child),
option:first-of-type {
margin-block-start: var(--size-2);
}
option:last-of-type,
&:last-child {
option:last-of-type {
margin-block-end: 0;
}
}
}
/* Option */
option {
/* Checkmark */
/* TODO - checkmark should be the final version of the checkmark API. Follow the development of this and remove redundant psuedo stuff. */
&::check {
display: none;
}
&::checkmark {
display: none;
}
&::before {
display: none;
}
&:focus-visible {
outline-offset: -1px;
}
}
}
}
:where(.select:has(select)) {
/* Size */
&.small {
button {
padding-inline: var(--size-2) var(--size-7);
&::after {
inset-inline-end: var(--size-2);
}
}
}
/*
* Non-experimental Select
*
* Hack to get the arrow working. Pseudo elements aren't allowed on the `<select>` element, so need to add it on the `.select` class instead. Noting this down if an `:after` element would be needed on a `.select`.
*/
&:not(:has(button)) {
select {
appearance: none;
}
/* Arrow */
&::after {
align-self: center;
block-size: 0;
border-block-start: 5px solid;
border-inline: 5px solid transparent;
content: "";
display: inline-block;
flex-shrink: 0;
grid-column: 1/-1;
grid-row: 2;
inline-size: 0;
inset-inline-end: var(--size-3);
justify-self: end;
pointer-events: none;
position: relative;
}
}
}
select:has(button),
::picker(select) {
appearance: base-select;
}
}
@layer components.extended {
/*
Lists meant to be used stand-alone or as part of Select elements
Intended use-case:
- ul.list > li
- .select > .list > option
*/
:where(.list) {
--_bg-color: var(--surface-filled);
--_bg-color-hover: oklch(from var(--primary) l c h / 15%);
background-color: var(--_bg-color);
color: var(--text-primary);
list-style: none;
padding: var(--size-2) 0;
@media (pointer: coarse) {
&,
* {
user-select: none;
}
}
/* Background color */
&.transparent {
--_bg-color: transparent;
}
&.default {
--_bg-color: var(--surface-default);
}
&.tonal {
--_bg-color: var(--surface-tonal);
}
/* Borders on all list items */
&.bordered {
:where(li + li, option + option) {
margin-block-start: var(--size-3);
&::before {
block-size: 1px;
border-block-start: 1px solid var(--border-color);
content: "";
display: block;
inline-size: 100%;
inset: calc(-1 * var(--size-2)) 0 auto 0;
position: absolute;
visibility: visible;
/* override select > option:before style */
}
}
}
/* Dense - less gaps and spacing */
&.dense {
:where(li, option) {
gap: var(--size-2);
min-block-size: var(--size-7);
padding: var(--size-1) var(--size-2);
&.border-top {
margin-block-start: var(--size-2);
&::before {
inset: calc(-1 * var(--size-1)) 0 auto 0;
}
}
/* Clickable list item */
&:has(> a, > button, > label) {
min-block-size: auto;
padding: 0;
}
&> :where(a, button, label) {
gap: var(--size-2);
min-block-size: var(--size-7);
padding: var(--size-1) var(--size-2);
}
/* Checkbox / Radio */
&>label {
.end {
padding-inline-end: 0.125rem;
}
&:where(.checkbox, .radio) {
--_input-size: var(--size-3);
}
}
/* Leading and trailing content */
.start,
.end {
.avatar {
max-inline-size: var(--size-6);
}
.icon-button,
svg {
max-inline-size: var(--size-4);
}
.checkbox,
.radio {
--_input-size: var(--size-3);
}
}
}
}
/* Gutterless */
&.gutterless {
:where(li, option) {
padding-inline: 0;
&> :where(a, button, label) {
padding-inline: 0;
}
}
}
/* List item */
:where(li, option, [role="group"] > label) {
align-items: center;
background-color: var(--_bg-color);
display: flex;
font-size: var(--font-size-05);
gap: var(--size-3);
isolation: isolate;
min-block-size: 40px;
padding: var(--size-2) var(--size-3);
position: relative;
&::before {
display: none;
/* removing checkmark from option */
}
* {
font-size: inherit;
}
/* Clickable list item */
&:has(> a, > button, > label) {
background: transparent;
display: block;
min-block-size: auto;
padding: 0;
&[aria-selected="true"]> :where(a, button, label),
&[aria-selected="true"],
&:has(> [aria-current="page"])> :where(a, button, label) {
background-color: var(--_bg-color-hover);
}
}
/* Select option */
&:where(option) {
align-items: center;
background-color: var(--_bg-color);
color: inherit;
cursor: pointer;
display: flex;
gap: var(--size-3);
inline-size: 100%;
margin: 0;
min-block-size: 40px;
padding: var(--size-2) var(--size-3);
text-align: start;
text-decoration: none;
z-index: 0;
&:hover {
background-color: var(--_bg-color-hover);
}
&[aria-selected="true"] {
background-color: var(--_bg-color-hover);
color: var(--primary);
}
&:checked {
background-color: oklch(from var(--primary) l c h / 30%);
}
}
&>a,
&>button,
&>label {
align-items: center;
background-color: var(--_bg-color);
color: inherit;
cursor: pointer;
display: flex;
gap: var(--size-3);
inline-size: 100%;
margin: 0;
min-block-size: 40px;
outline-offset: -3px;
padding: var(--size-2) var(--size-3);
text-align: start;
text-decoration: none;
z-index: 0;
&:hover {
background-color: var(--_bg-color-hover);
}
&[aria-selected="true"],
&[aria-current="page"] {
background-color: var(--_bg-color-hover);
}
}
/* Checkbox / Radio / Switch */
&>label {
&:where(.checkbox, .radio, .switch) {
display: flex;
}
.end {
padding-inline-end: var(--size-1);
}
&:where(.checkbox, .radio) {
inline-size: 100%;
}
/* Switches look comically big in lists, so it's better to use a smaller variant */
&.switch {
--_dot-size: 0.75rem;
--_track-height: var(--size-4);
--_track-width: 2.5rem;
}
}
/* Video */
&:has(video) {
padding: 0.75rem var(--size-3) 0.75rem 0;
}
/* Border between list items */
&.border-top {
margin-block-start: var(--size-3);
&::before {
block-size: 1px;
border-block-start: 1px solid var(--border-color);
content: "";
display: block;
inline-size: 100%;
inset: calc(-1 * var(--size-2)) 0 auto 0;
position: absolute;
}
}
/* Text */
.text {
flex: 1;
line-height: 1.6;
:where(h1, h2, h3, h4, h5, h6, p, span) {
color: inherit;
font-weight: 400;
}
p+p {
color: var(--text-muted);
font-size: var(--font-size-0);
}
}
/* Leading content */
.start {
align-items: center;
align-self: center;
display: grid;
z-index: 1;
&:has(svg) {
max-inline-size: var(--size-5);
}
svg {
padding-block-start: 0.125rem;
}
img {
aspect-ratio: 1;
inline-size: 56px;
object-fit: cover;
}
video {
aspect-ratio: 16/9;
block-size: 64px;
object-fit: cover;
}
}
/* Trailing content */
.end {
align-items: center;
display: flex;
font-size: var(--font-size-0);
text-align: end;
z-index: 1;
&:not(:has(a, button, input)) {
pointer-events: none;
}
kbd {
background-color: transparent;
border: 0;
color: inherit;
opacity: 0.6;
}
svg {
inline-size: 100%;
max-inline-size: var(--size-5);
}
}
/* Inset */
&.inset {
.text {
padding-inline-start: calc(var(--size-5) + var(--size-3));
}
/* Safety measure so it won't look bad if there for some reason should exist a leading element inside. */
.start {
display: none;
}
}
}
}
}

See also