How to create an accordion in HTML
Most of the time the functionality of accordions on the web is built with JavaScript. That could work, but did you know there is a better way? Meet the native HTML <details>
element.
See the Pen Details element by Rogier (@rvwebdev) on CodePen.
The <details>
element, also known as the details disclosure element, has built-in functionality to toggle between an open and closed state. Opening or closing the element toggles an open
attribute on the <details>
element. The pros of this are that this element works as an accordion out of the box, without the use of CSS or JavaScript.
Optional enhancements
So the <details>
element already works as an accordion element. But we can enhance it with some CSS and JavaScript to make it even better while still being accessible.
CSS enhancement
First we will be adding a pointer cursor to the <summary>
element to make it more clear that it can be clicked.
summary {
cursor: pointer;
}
To remove the default toggle icon, we can add the following CSS.
summary {
list-style-type: none;
}
summary::-webkit-details-marker {
display: none;
}
To add our custom toggle icon, we can use the ::before
pseudo element. For now we are using a plus and minus character to indicicate the open or closed state.
details summary::before {
content: '+';
display: inline-block;
width: 1rem;
height: 1rem;
}
/* when details is opened */
details[open] summary::before {
content: '-';
}
JavaScript enhancement
To only have one accordion open at all times, we can add some JavaScript. We will need a function that will close all other details
elements when the clicked <details>
element is opened.
function toggleHandler (event) {
// Only run if accordion is open
if (!event.target.hasAttribute('open')) return;
// Get all open accordions inside parent
let opened = document.querySelectorAll('details[open]');
// Close open ones that aren't current accordion
for (let accordion of opened) {
if (accordion === event.target) continue;
accordion.removeAttribute('open');
}
}
After this, we will listen for a toggle event on the document and call the toggleHandler
function.
// The toggle event doesn't bubble, so we need to set the optional third argument, useCapture, to true.
document.addEventListener('toggle', toggleHandler, true);
Result
And there we go! We have an accordion element enchanced with CSS and JavaScript!