This post is about closing all details tag when another one is open.
I was writing a post about MidDay,
my new WordPress Theme, and wanted to include a
simple FAQ section but with a little of style, this is when I remembered the
<details>
tag.
It's an awesome accessible element, similar to an accordion.
How to create one?
You have just opened one 😁Just follow the pattern in the code.
<details>
<summary>Summary/Question about the content</summary>
And here is the content, it could be anything, even code like this example 😉
</details>
But when we use more than one <details>
tag on the same page, especially
when they are one after another, we can see that if one is opened and we open another one,
the first stays opened.
Imagine having 5 or more after each other, with a reasonable
amount of content, they will take a lot of space. As an example, you can take a look at this
informative pen:
Teaching the Details Element with ... Details Elements!
So how to close the opened one?
Easy!Just include the following code in your scripts file or in a
script
tag at the
bottom of your page before the closing body
tag.
/** Close others <details> tag */
const allDetails = document.querySelectorAll("details")
allDetails.forEach((details) => {
details.addEventListener("toggle", (e) => {
if (details.open) {
allDetails.forEach((details) => {
if (details != e.target && details.open) {
details.open = false
}
})
}
})
})
Let's break it down!
First we select all the <details>
tag:
const allDetails = document.querySelectorAll("details")
And we iterate over them:
allDetails.forEach(details => {
Then we listen to the toggle
event used by the
<details>
element whenever its state changes between open and closed:
details.addEventListener('toggle', (e) => {
Now, we wait for any <details>
to be open
:
if (details.open) {
We iterate once again over all the <details>
and check if anyone of them
was not the target
of the toggle
event and was open
,
if so, we just close it by removing it's open state:
allDetails.forEach((details) => {
if (details != e.target && details.open) {
details.open = false
}
})
In other words, if a <details>
element was opened, it have the
open
attribute. Now if another <details>
element is open, we
remove the open
attribute from the previous, leaving only the actual targeted
one opened.
Hope that this was useful, and that you'll start using The Details disclosure element.