Accordion
Native details rows that open to their own height.
On this page
An accordion is a list of rows that open in place. Each row is a native <details> with a <summary>, so the browser keeps the toggle, the keys and find-in-page, which opens a closed row when it holds a match. The stylesheet draws the rows on hairlines and lets each panel open to its own height.
Accordion
<div class="accordion"> <details class="accordion-item" name="faq" open> <summary class="accordion-trigger">Does it need JavaScript?</summary> <div class="accordion-content">No. Every component is a native element with one stylesheet; the browser keeps its behavior.</div> </details> <details class="accordion-item" name="faq"> <summary class="accordion-trigger">Can I change the radius?</summary> <div class="accordion-content">Yes. Override the radius tokens after importing Master UI, or set a component's own property such as --btn-radius.</div> </details> <details class="accordion-item" name="faq"> <summary class="accordion-trigger">Is dark mode a second stylesheet?</summary> <div class="accordion-content">No. Every color token resolves with light-dark(), following the page's color scheme.</div> </details></div>#One at a time, or many
Rows that share a name attribute form a group: opening one closes the others, as above. Leave name out to let any number stay open.
Independent rows
<div class="accordion"> <details class="accordion-item" open> <summary class="accordion-trigger">Build</summary> <div class="accordion-content">Installed 412 packages in 9 seconds and compiled 38 routes.</div> </details> <details class="accordion-item" open> <summary class="accordion-trigger">Deploy</summary> <div class="accordion-content">Uploaded 3.1 MB to 14 regions.</div> </details> <details class="accordion-item"> <summary class="accordion-trigger">Checks</summary> <div class="accordion-content">All 6 checks passed.</div> </details></div>#On a surface
The accordion has no material of its own. Put it in a card or a sheet for a boxed list.
In a card
<section class="card"> <header class="card-header"> <h3 class="card-title">Shipping</h3> <p class="card-description">Rates and delivery times.</p> </header> <div class="accordion"> <details class="accordion-item" name="shipping"> <summary class="accordion-trigger">Domestic</summary> <div class="accordion-content">Two to four working days. Free above 50 USD.</div> </details> <details class="accordion-item" name="shipping"> <summary class="accordion-trigger">International</summary> <div class="accordion-content">Five to ten working days, with tracking.</div> </details> </div></section>#Motion
The panel is the ::details-content pseudo-element. interpolate-size: allow-keywords lets its block-size travel from 0 to auto, and content-visibility transitions with allow-discrete so the text stays painted until the panel has closed. The chevron turns over with it. In a browser without these the panel opens at once; with reduced motion it fades in place.
#Classes
| Class | Description |
|---|---|
accordion | The list of rows |
accordion-item | A row, on a details element; a hairline parts it from the next |
accordion-trigger | The row's title, on the summary, with a chevron at its end |
accordion-content | The panel: running text under the title |