blog

Animating auto height for accordion component

Accordion component is an element with a title and some content that can get hidden or displayed by clicking the title. There is a native HTML version of that done with a combination of <details> and <summary> elements but without built-in animation. At Hugo, we have Preact component called Panel.

I know a couple of ways of getting Panel to animate:

1. Animating max-height

You can’t animate between numeric and auto values in CSS. So instead we animate between two numeric values of max-height property. Starting value will be 0 and end value will be some arbitrary number, large enough so the content inside doesn’t get clipped.

.content {
overflow: hidden;
max-height: 0;
transition: max-height 0.3s ease;
}
#state:checked ~ .content {
max-height: 150px;
}

Here is a CSS-only demo, using good ’ol checkbox hack:

See the Pen Accordion animation by Teo Dragovic (@teodragovic) on CodePen.

2. Using React Animate Height

React Animate Height does exactly what it says. It’s a nice, little utility library that helps animate React components using CSS. I used it to avoid dealing with event handling myself.

<div className="c-panel__content">
<AnimateHeight height={ expanded ? 'auto' : 0 }>
{ children }
</AnimateHeight>
</div>

3. Using JavaScript

In an attempt to reduce our bundle size and number of dependencies, I dropped React Animate Height in favor of a simple, custom approach.

See the Pen Preact Panel by Teo Dragovic (@teodragovic) on CodePen.

We didn’t have any uses for animating height outside Panel component and that itself was used only in a few places so this super lightweight approach worked for us.

4. Using CSS Grid

Great trick by Nelson Menezes (and reposted by CSS-Tricks) by using CSS Grid. This is my current prefferd approach.

.expander {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 1s;
overflow: hidden;
}

.expander.expanded {
grid-template-rows: 1fr;
}

See the Pen Preact Panel by Teo Dragovic (@teodragovic) on CodePen.