Accordion
Accordion — a disclosure, and a group of them.
Examples
Shipping
Returns
Warranty
<details class="accordion" name="faq" open>
<summary class="accordion-trigger">Shipping</summary>
<div class="accordion-panel">Orders leave the warehouse next day.</div>
</details>
<details class="accordion" name="faq">
<summary class="accordion-trigger">Returns</summary>
<div class="accordion-panel">Thirty days, no questions asked.</div>
</details>
<details class="accordion" name="faq">
<summary class="accordion-trigger">Warranty</summary>
<div class="accordion-panel">Two years on parts and labour.</div>
</details>The shared name is what makes the group exclusive — the browser closes the siblings, with no script and no wrapper element. Remove it and each item is an independent collapsible.
Advanced options
<details class="accordion">
<summary class="accordion-trigger">Advanced options</summary>
<div class="accordion-panel">Nothing here changes how the export is produced.</div>
</details>Same component without name. That attribute is the entire difference between a collapsible and an accordion.
Installing
<details class="accordion" name="chapters">
<summary class="accordion-trigger"><h3>Installing</h3></summary>
<div class="accordion-panel">A single link tag is the whole integration.</div>
</details>A heading inside the summary is valid HTML and is what puts the item in the document outline. Use it when the accordion is the page, not an aside.
Tokens 21
Level 2, declared on .accordion itself. Set any of them on that selector to restyle this component without touching the skin.
| Token | Default |
|---|---|
| --accordion-marker-color | var(--color-on-surface-muted) |
| --accordion-marker-size | 0.4em |
| --accordion-panel-color | var(--color-on-surface-muted) |
| --accordion-panel-font-size | var(--font-size-sm) |
| --accordion-panel-padding-block | var(--space-4) |
| --accordion-panel-padding-inline | var(--space-4) |
| --accordion-trigger-font-family | var(--font-secondary) |
| --accordion-trigger-gap | var(--space-3) |
| --accordion-trigger-padding-block | var(--space-3) |
| --accordion-trigger-padding-inline | var(--space-4) |
| --accordion-bg | var(--color-surface-raised) |
| --accordion-border-color | var(--color-border) |
| --accordion-border-width | var(--border-width) |
| --accordion-color | var(--color-on-surface) |
| --accordion-radius | var(--radius-box) |
| --accordion-duration | var(--duration-normal) |
| --accordion-gap | var(--space-1) |
| --accordion-panel-padding-block-start | var(--space-2) |
| --accordion-trigger-font-size | var(--font-size-sm) |
| --accordion-trigger-font-weight | var(--font-weight-medium) |
| --accordion-trigger-hover-bg | var(--color-surface-sunken) |
Variants and states
Variants
None. It is one shape, and the page does the rest.
Inside it
.accordion-trigger.accordion-flush.accordion-panel
State it reads
Read from the platform, never mirrored into a class that could disagree with it.
:focus:hover[open]data-legacy
Before you ship it
What you have to do 5 requirements
- Give every item in a group the same
name. A typo does not error; it quietly produces an item that opens on its own. nameandopenconflict: only the lastopenitem in a named group stays open. Mark at most one.- When the accordion is page structure rather than an aside, put heading content inside the summary —
<summary class="accordion-trigger"><h3>…is valid HTML and is what puts the item in the document outline. The reset already makes the heading inherit its surroundings. - A panel holding more than one block of copy wants
.proseon it: the reset zeroes margins, so bare<p>siblings inside a panel sit flush together..prosealso restores full-contrast body colour over the panel's muted default, which is what you want for real running text. .accordionclips its own corners withoverflow: hidden, so an overlay inside a panel must be one the browser promotes to the top layer (popover,<dialog>); an absolutely positioned one will be cut off.
src/css/components/accordion.css · npx mostlycss add accordion