CSS collapse
Five techniques for expanding and collapsing content — four with CSS alone, one with JavaScript for contrast.
What makes this approach special?
The browser handles open/closed state entirely. The open attribute is toggled automatically, giving you a reliable CSS hook. The downside: discrete open/close with no transition — content just appears.
Can I style the disclosure marker?
Yes — use summary::marker or summary::-webkit-details-markerto swap or hide it. Replace it with your own icon via ::before and rotate on [open].
The checkbox's :checked pseudo-class is the state machine. Because the label and content are siblings of the checkbox in the DOM, you can target them with:checked ~ label and :checked ~ .body. The browser tracks checked state natively.
Accessibility is the main concern — screen readers announce this as a checkbox, not a disclosure widget. You can patch it with role="button" andaria-expanded on the label, but at that point a small JS sprinkle is cleaner.
CSS can't interpolate between height: 0 and height: autobecause "auto" isn't a numeric value. But grid-template-rows: 0fr → 1fris numeric — the browser knows exactly how to tween it. The content's natural height becomes the 1fr track and collapses to zero cleanly.
All modern browsers since 2023. The transition on grid-template-rowslanded in Chrome 107, Safari 16, and Firefox 110. It's safe to use without a fallback for most production sites today.
Likely yes. interpolate-size alongside the calc-size()function is the spec's intended solution. The mental model is the simplest of any technique here: animate height like you'd animate any other property. Currently Chrome 129+ and Edge 129+; Firefox and Safari support is in progress.
Setting interpolate-size: allow-keywords on :root is a broad opt-in — it changes how all keyword-to-length interpolations work in the document. Scope it carefully if you're mixing with other animation libraries that do their own height tweening.
When you need logic the browser can't supply through state alone: closing other panels when one opens, persisting open state across navigations, deep-linking, or animating things that CSS transitions can't express. The CSS techniques above cover a surprising amount of ground first.
For simple content disclosure, yes — <details> is semantically correct, keyboard-accessible, and zero-dependency. Reach for a JS accordion when you need animation, mutual exclusion (only one panel open at a time), or richer ARIA patterns like role="tabpanel".