How to fully animate the details HTML element with only CSS, no JavaScript

jgustavoas

Gustavo Alexandrino

Posted on January 9, 2023

How to fully animate the details HTML element with only CSS, no JavaScript

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 */
}
Enter fullscreen mode Exit fullscreen mode

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:

  1. Using the + adjacent sibling combinator
  2. 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 */
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
jgustavoas
Gustavo Alexandrino

Posted on January 9, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related