The devil is in the <details>
by J. Pedro Ribeiro published on
Not too long ago, building an accordion component would require you to use a combination of JavaScript and CSS. If you've been around for as long as I have, you might have used a library like jQuery or Mootools.
If you went "vanilla", your code would look something like this:
<div class="my-js-accordion">
<span>Learn more about accordions</span>
<p class="hidden">Accordions encapsulate content under a heading.</span>
</div>
.hidden {
display: none;
}
document.querySelectorAll(".my-js-accordion").forEach((accordion)=>{
accordion.querySelector("span").addEventListener("click", (e)=>{
accordion.querySelector("p").classList.toggle("hidden");
});
});
And it would work as you expected:
Accordions encapsulate content under a heading.
We needed JavaScript and CSS to make this work. Click the heading again to close it.
For any other advanced feature, more JavaScript will be needed.
The more adventurous would hack together some input
and label
elements together. With the help of :checked
and some clever
CSS selectors, you could achieve the same visual representation as the one above but without the need for JavaScript.
<div class="my-css-accordion">
<input type="checkbox" id="accordion1">
<label for="accordion1">→ Learn more about accordions</label>
<p>Accordions encapsulate content under a heading.</p>
</div>
.my-css-accordion input[type="checkbox"],
.my-css-accordion p {
display: none;
}
.my-css-accordion input[type="checkbox"]:checked + label + p {
display: block;
}
And it would be visually the same as the previous example:
Accordions encapsulate content under a heading.
Only CSS and HTML!
However, the code is slightly harder to maintain
These techniques work but there have some disadvantages: not only they're hard to maintain, they're also not accessible, and their reliance on JavaScript makes them not the ideal candidate for a modern web application.
In summary, another case of HTMLHell.
Here comes a new challenger
Since 2020, all major browsers support the <details>
and its companion <summary>
elements. Combined, they replace the need for JavaScript and CSS hacks to create an accordion component.
We use the following syntax:
<details>
<summary>Your heading goes here</summary>
<p>Any content you like goes below the summary tag.</p>
<p>As many elements as you need.</p>
</details>
And it will work just like the previous examples, but with some added benefits:
- Less code ✅
- Fully accessible ✅
- Works without JavaScript ✅
- No need for hacks ✅
- Fully stylable ✅
As seen below:
Your heading goes here
Any content you like goes below the summary tag.
As many elements as you need.
This is the second heading
Any content you like goes below the summary tag.
As many elements as you need.
And the third entry it's here
Any content you like goes below the summary tag.
As many elements as you need.
On the example above, each <details>
element works independently of each other. But what if you want them to behave like true accordions, where only one can be opened at a time?
One More Thing... Exclusive Accordions
Not too long ago, the name
attribute was added to the details
element.
Similarly to the usage in the radio input, it allows you to group multiple elements together. This means we can have exclusive accordions: when only one can be opened at a time.
Here is an example of the usage:
<details name="my-accordion-group">...</details>
<details name="my-accordion-group">...</details>
<details name="my-accordion-group">...</details>
Give the same name
attribute to all the details
elements you want to group together and they'll work as expected:
3 separate entries
First block content.
End of first block.
Only one can be opened at a time
Second block content.
End of second block.
Still, no JS needed!
Third block content.
End of third block.
Note: It's worth highlighting that exclusive accordion come with some drawbacks, including poor UX on keyboard navigation and reduced usability for screen readers. Eric Eggert wrote about these issues, offering some solutions and insights that are worth reading.
Take it to the next level
Recently, Chrome 131 added support to new ways you can style both <details>
and <summary>
elements. Still early days but the future looks bright!
Combine these features with some creative styling and you can create really complex components with accessibility and scalability built-in.
Further reading and examples:
Code snippets | MDN | Can I use | web.dev
About J. Pedro Ribeiro
J. Pedro Ribeiro is Brazilian frontend developer who loves to build performant sites and apps that deliver great user experience.
Blog: jpedroribeiro.com
On X (Twitter): @jpedroribeiro
On LinkedIn: LinkedIn