Mastering the Art of Custom Accordions: Details and Summary Styling
Grab a coffee and pull up a chair. We’ve all been there: a client asks for a slick, animated FAQ section or a nested accordion, and your first instinct is to reach for a heavy JavaScript library or start writing useState hooks in React. But why? The browser already gives us the <details> and <summary> tags. For a long time, these were the "ugly ducklings" of HTML—functional, but visually stubborn. Today, I’m going to show you how to turn these semantic workhorses into high-end UI components using nothing but modern CSS.
How we suffered before
Remember the "Checkbox Hack"? It was the wild west of frontend. If you wanted a toggleable element without JavaScript, you had to hide an <input type="checkbox">, use a <label> to trigger it, and then use the adjacent sibling combinator (+ or ~) to show or hide a <div>. It was a semantic nightmare and a headache for screen readers.
When <details> first arrived, it was better, but styling the "triangle" was a pain. We had to use non-standard pseudo-elements like ::-webkit-details-marker just to hide the default arrow. If you wanted a smooth height transition, you were out of luck—CSS simply couldn't animate from height: 0 to height: auto. We often ended up writing messy JS scripts to calculate scrollHeight on the fly. To understand how far we've come with modern motion, you might want to revisit our article on Advanced CSS Animations: Keyframes vs Transitions.
The modern way in 2026
In 2026, styling these elements is a breeze. We have ::marker to handle the icons, flex or grid to align the summary content, and—the absolute game-changer—the interpolate-size property which finally allows us to animate to auto height.
The modern approach involves treating the <summary> as a flex container. This lets us put icons on the left, text in the middle, and status indicators on the right without breaking a sweat. We also use the [open] attribute selector to change styles when the content is revealed. If you're building complex layouts, combine this with Style Queries: Container Style Queries to make your accordions react to their parent container's dimensions or styles.
Ready-to-use code snippet
Here is a clean, modern implementation. It features a custom animated plus/minus icon and a smooth reveal effect using interpolate-size (supported in the latest browsers).
<style>
:root {
interpolate-size: allow-keywords;
}
.custom-accordion {
max-width: 500px;
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
font-family: sans-serif;
}
details {
border-bottom: 1px solid #e0e0e0;
transition: background 0.3s ease;
}
details:last-child {
border-bottom: none;
}
details[open] {
background: #f9f9f9;
}
summary {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem;
cursor: pointer;
list-style: none; /* Removes default arrow */
font-weight: 600;
}
/* Standard way to hide the marker */
summary::-webkit-details-marker {
display: none;
}
summary::after {
content: '+';
font-size: 1.5rem;
transition: transform 0.3s ease;
}
details[open] summary::after {
transform: rotate(45deg);
}
.content {
padding: 0 1rem 1rem;
height: 0;
overflow: hidden;
transition: height 0.4s ease-out, opacity 0.3s ease;
opacity: 0;
}
details[open] .content {
height: auto;
opacity: 1;
}
</style>
<div class="custom-accordion">
<details>
<summary>What is the benefit of this approach?</summary>
<div class="content">
<p>It is lightweight, accessible by default, and requires zero JavaScript for the core functionality.</p>
</div>
</details>
<details>
<summary>Is it SEO friendly?</summary>
<div class="content">
<p>Absolutely! Search engines see the content immediately because it is present in the DOM from the start.</p>
</div>
</details>
</div>
Common beginner mistake
The biggest mistake I see? People forget that <summary> has a default display: list-item in many browsers. If you try to apply display: flex to it without realizing this, you might run into weird layout bugs or find that the default "triangle" arrow refuses to disappear in certain browsers like Safari. Always explicitly hide the ::marker and the non-standard ::-webkit-details-marker if you are providing your own icon.
Also, avoid putting interactive elements like buttons or links directly inside the <summary> tag. The summary itself acts as a button; putting a button inside a button is a classic accessibility fail that will confuse screen reader users and potentially break the toggle behavior.
🔥 We publish more advanced CSS tricks, ready-to-use snippets, and tutorials in our Telegram channel. Subscribe so you don't miss out!
Top comments (0)