Home / Snippets / UI Components /
CSS accordion
details / summary styled — open/close behavior is built-in.
What is CSS Anchor Positioning?
Is :has() widely supported?
What is animation-timeline?
Quick implementation
/* HTML: <details class="acc-item"><summary>Title <span class="acc-icon">+</span></summary><div class="acc-content">...</div></details> */
.acc-item {
border: 1px solid oklch(0 0 0 / 0.07);
border-radius: 0.75rem;
overflow: hidden;
background: white;
}
.acc-item summary {
display: flex; align-items: center; justify-content: space-between;
padding: 0.85rem 1.1rem;
cursor: pointer; font-weight: 600;
list-style: none; /* hide default triangle */
}
.acc-item summary::-webkit-details-marker { display: none; }
/* Rotate icon on open */
.acc-icon {
font-size: 0.8rem;
transition: transform 0.25s;
}
.acc-item[open] .acc-icon { transform: rotate(45deg); }
/* Style summary when open */
.acc-item[open] summary { color: oklch(0.52 0.22 265); }
.acc-content {
padding: 0 1.1rem 0.85rem;
border-top: 1px solid oklch(0 0 0 / 0.07);
font-size: 0.875rem; color: oklch(0.48 0.025 260);
}
/* Smooth height transition (new — requires interpolate-size) */
@supports (interpolate-size: allow-keywords) {
:root { interpolate-size: allow-keywords; }
}
Prompt this to your LLM
Includes animated height transition and React variant.
You are a senior frontend engineer building accessible UI components.
Goal: A styled FAQ accordion using <details>/<summary> — no JavaScript for open/close.
Technical constraints:
- Use <details> and <summary> for native open/close. Style with .acc-item[open] for open state.
- Hide the default marker: summary { list-style: none } + summary::-webkit-details-marker { display: none }.
- Show a +/× icon (or SVG chevron) via a <span> inside summary, rotated on [open] with transform: rotate(45deg).
- Each panel's content sits in a <div class="acc-content"> below the summary.
- Use border-radius on the item, a subtle border, and a border-top on the content area.
Animated height transition (bonus):
- Use interpolate-size: allow-keywords in :root and transition: height on details to get smooth open/close in browsers that support it. Provide a non-animated fallback for others.
Framework variant (pick one):
A) Vanilla HTML + CSS — a 3-item FAQ.
B) React — an Accordion component that accepts items as an array of { question, answer } props. The [open] attribute is managed by the browser; no React state needed.
Edge cases:
- Multiple open at once (default behavior with details).
- To restrict to one open at a time, note that a <details name="group"> attribute (new, limited support) or a small JS pattern would be needed.
Return full HTML + CSS.
Why this matters in 2026
Accordions are everywhere — FAQ sections, settings panels, mobile nav. Using <details>/<summary> gives you open/close for free, including keyboard (Enter/Space) and screen reader support. CSS handles the visual state with [open]. No useState, no event listeners, no bundle cost.
In 2026, the interpolate-size: allow-keywords property (shipping in Chrome 129+) finally enables smooth height transitions on details elements using transition: height — something that previously required JavaScript or max-height hacks.
The logic
The [open] attribute is toggled by the browser when the user clicks the summary. .acc-item[open] .acc-icon rotates the plus icon. .acc-item[open] summary colors the trigger. The content panel shows because it's a normal child of the <details> element — no display toggling needed.
The details[name] attribute (new, partial support) allows multiple <details> to share a group name so only one is open at a time — like a proper "exclusive accordion." Use it as a progressive enhancement.
Accessibility & performance
The <details> element has full ARIA semantics built in. Screen readers announce "expanded" and "collapsed". Keyboard users can tab to the summary and toggle with Enter or Space. Don't add role="button" to the summary — it already is one. Zero JavaScript means the accordion works during page load before scripts execute.