This content originally appeared on DEV Community and was authored by Muhammad Sulais
The HTML <details>
element allows you to expand and shrink content effortlessly. Here's a basic implementation of <details>
:
<details id="my-details">
<summary>Click me to expand</summary>
<!-- Your content here -->
</details>
While this element is great, you might wonder how to add a smooth transition effect with CSS alone:
details#my-details {
transition-duration: 300ms;
}
However, using just CSS doesn’t apply any transition effect when toggling the element. To achieve this, you need to use some JavaScript.
Solution
First, wrap the content within the <details>
element with another element. In this example, we use a <div>
as the content wrapper:
<details id="my-details">
<summary>Click me to expand</summary>
<div>
<!-- Your content here -->
</div>
</details>
Although the animation typically works as expected, there are certain conditions where you might need to apply
overflow: hidden
to the content wrapper to achieve the desired effect.
Next, we add the JavaScript to handle the transition effect:
const details = document.getElementById("my-details");
const summary = details.firstElementChild;
const content = summary.nextElementSibling;
let isAnimating = false;
summary.onclick = (ev) => {
ev.preventDefault();
if (isAnimating) return;
const contentHeight = content.getBoundingClientRect().height;
isAnimating = true;
// Closing <details>
if (details.open) {
return content
.animate(
{ height: [contentHeight + 'px', '0px'] },
{ duration: 300 }
)
.finished
.then(() => details.open = isAnimating = false);
}
// Opening <details>
details.open = true;
content.animate(
{ height: ['0px', contentHeight + 'px'] },
{ duration: 300 }
).finished.then(() => isAnimating = false);
};
Now, when you toggle the <details>
, it will animate the transition.
But wait, how exactly does this work?
Explanation
Let’s break down the JavaScript code. The simplest way to animate an element is by using the animate()
method, which accepts two arguments: keyframes
and options
. We'll explore its details in another post, but here's a quick overview.
To achieve the animation, we prevent the default behavior of the <summary>
element to disable its instant toggle functionality:
summary.onclick = (ev) => {
ev.preventDefault();
};
Next, we obtain the height of the <details>
content:
const contentHeight = content.getBoundingClientRect().height;
If the <details>
is open, indicated by the open
property, we animate the content height from its default height to 0px
and set details.open
to false
after the animation ends:
// Closing <details>
if (details.open) {
return content
.animate(
{ height: [contentHeight + 'px', '0px'] },
{ duration: 300 }
)
.finished
.then(() => details.open = isAnimating = false);
}
When opening <details>
, we:
- Animate the content height from
0px
to its default height. - Set
details.open
totrue
before the animation starts.
// Opening <details>
details.open = true;
content.animate(
{ height: ['0px', contentHeight + 'px'] },
{ duration: 300 }
).finished.then(() => isAnimating = false);
Understanding the isAnimating
Variable
The isAnimating
variable is used to determine if an animation is currently running. If an animation is in progress, further toggle actions are prevented until the animation completes:
let isAnimating = false;
summary.onclick = (ev) => {
ev.preventDefault();
if (isAnimating) return;
isAnimating = true; // mark as not done
content.animate(/* ... */)
.finished
.then(() => isAnimating = false) // mark as done
};
Conclusion
These transition effects aren’t limited to height changes. You can use any CSS properties to animate the <details>
element. The animate()
method is a powerful way to create engaging, visually appealing web interactions.
This content originally appeared on DEV Community and was authored by Muhammad Sulais
Muhammad Sulais | Sciencx (2025-01-26T05:00:00+00:00) How I made toggle transition to <details> element. Retrieved from https://www.scien.cx/2025/01/26/how-i-made-toggle-transition-to-details-element/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.