Yes, this includes animating the closing of the element too!
Introduction
Animating the <details>
HTML element using only pure CSS can be a challenging task, as many articles, posts, and tutorials either rely on JavaScript or offer incomplete solutions that are unable to animate the closing of the element or produce a smooth animation.
However, with a bit of creativity, it is possible to create a fully-animated <details>
element using pure CSS.
This solution reproduces the example from Chris Coyier's CSS Tricks post, but achieves the same smooth animation without using any JavaScript – only CSS – for both opening and closing the element.
The CSS Solution
The key is to start the page with the details
element in its open state (<details open>
), then change its max-height
value by toggling a checkbox, and use a transition effect to animate that change.
details {
max-height: 4rem; /* Set a max-height value just enough to show the summary */
overflow: hidden; /* Hide the rest of the content */
transition: max-height 400ms ease-out; /* Animate the change */
}
To control the change of the element's max-height
value, you will need a checkbox and associate it with the <details>
element. You can choose from two approaches to do this, and both work great:
- Using the
+
adjacent sibling combinator - Using the
:has()
pseudo-class
input:checked + details,
details:has(input:checked) {
max-height: 576px; /* Set a max-height value enough to show all the content */
}
In the CSS, the selector input:checked + details
selects a <details>
element that immediately follows a checked input element. On the other hand, the selector details:has(input:checked)
selects a <details>
element that has a checked input element as its descendant.
The HTML
The difference between the two approaches in HTML is that the checkbox input must come immediately before the <details>
element in the first approach, and the checkbox must be a descendant of the <details>
element in the second approach.
Inside the <summary>
tag of the <details>
element , place a <label>
that toggles the checkbox:
<!-- approach #1 (checkbox comes immediately before the details element) -->
<input type="checkbox" name="approach-one" id="approach-one" />
<details open>
<summary>
<label for="approach-one">This one uses the adjacent sibling combinator (+) approach</label>
</summary>
<div class="rest-of-the-content">...</div>
</details>
<!-- approach #2 (checkbox is a descendant of the details element -->
<details open>
<summary>
<input type="checkbox" name="approach-two" id="approach-two" />
<label for="approach-two">This one uses :has() pseudo-class approach</label>
</summary>
<div class="rest-of-the-content">...</div>
</details>
A note about Firefox browser
One caveat to consider when using the :has()
approach is that in Firefox the user must explicitly enable this feature (see caniuse.com and MDN Web Docs).
Final result
Top comments (3)
Update on June 2023: check the version that works in Safari and Firefox on macOS.
dev.to/jgustavoas/solved-how-to-fu...
Don't try this at home, kids! Checkbox hack are never a good idea, and the method has several shortcomings.
dev.to - A constructive and inclusive social network for software developers. But the idea shown here excludes people who don't use vision and mouse/touch. Very sad.
Sadly this solution doesn't work in Safari. It seems to be because of poor support of that browser for the
<summary>
element and the::marker
pseudo-element.It is also odd to note that in Firefox on MacOS this solution doesn't work at all, unlike other OS, where only the approach with the
:has()
pseudo-class doesn't work in Firefox by default.