Toggle Animation on Click with Dynamic Height
This is to implement the expand/collapse of an element with animation. For example, when a user clicks on a button, some content shows up and clicks again, it disappears.
It's a pretty straightforward case for displaying or hiding some content based on state. A simple
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
<div className={`content ${isOpen ? "open" : ""}`}>
<span style={{ padding: "5px" }}> This is the content</span>
<ol style={{ paddingLeft: "8px" }}>
<li role="listitem">
<span>List1</span>
</li>
<li role="listitem">
<span>List2</span>
</li>
</ol>
</div>
</div>
And then in the css, makes the initial element (className content here) height 0 and then with className open, set height to a fixed number.
.content {
height: 0px;
overflow: hidden;
transition: height 1s ease-in-out;
}
.content.open {
height: 200px;
}
The transition works just fine.
However, if we have the content with dynamic length and try to set it to:
.content.open{
height: auto
}
Transition would stop working. The reason is that CSS transitions cannot animate from a fixed value to auto
. The browser doesn't know how to smoothly transition from 0px
to an "automatic" height, as auto
is not a numerical value that can be interpolated.
Also tried to change height
to max-height
, no dice.
The trick here is to dynamically calculate the content height. This can help you transition the element from 0px
to its actual content height without hardcoding a large value.
At first we can measure the content natural height before the transition starts. And then transition the height
property by dynamically setting the height based on the content's natural height.