Pure-CSS accordion
No JS. <details> is underused.
An accordion component — expandable sections that reveal content when clicked — built entirely in CSS using the native <details> and <summary> elements.
The Challenge
Build an accordion where clicking a section header reveals the section body. Only one section should be open at a time. No JavaScript.
The native solution: <details> elements are interactive by default. The browser handles open/close state with no JS required.
The Implementation
<details class="accordion-item"> <summary class="accordion-header">What is this?</summary> <div class="accordion-body"> <p>Content that reveals when the header is clicked.</p> </div></details>The <details> element manages its own open/closed state. Add the open attribute to start open. Remove it to start closed.
Styling the Arrow
The default triangle marker on <summary> can be replaced:
summary { list-style: none; cursor: pointer; display: flex; justify-content: space-between; align-items: center;}
summary::after { content: "+"; transition: transform 0.2s;}
details[open] summary::after { transform: rotate(45deg);}Animated Open
Animating the expand is the tricky part — you can’t animate height: auto in CSS. One approach:
.accordion-body { overflow: hidden; max-height: 0; transition: max-height 0.3s ease;}
details[open] .accordion-body { max-height: 500px;}This works but the closing animation is abrupt. The @starting-style rule (newly supported) solves this properly, but <details> + CSS alone gets you 90% there.
Why It Matters
The <details> element is semantically correct for disclosure patterns. It’s accessible by default — keyboard navigable, announced correctly by screen readers — which a DIV-based implementation requires extra ARIA to replicate.