Last Updated: January 13, 2021
Share this:
JavaScript CSS Basics

How To Do CSS Transitions With Height: Auto

Creating a smooth expand/collapse animation seems easy. Surely you can set a transition on height: auto, and it'll just work?

Sadly, the CSS gods aren't so kind.

Instead of the smooth open and close you envisaged, your element suddenly reappears at its new height. No smooth animation. Not what you pictured at all.

As it turns out, animating on CSS auto values doesn't work, and it's honestly a real shame. The only way the CSS animation will work is if we know the size of our elements in advance - a luxury we rarely have.

The bad news is that there isn't a universal best approach, but there are still several options at our disposal.

Method 1: Use transform

Despite its rampant use, you should generally avoid CSS transitions on the height or width properties (among some others).

These properties affect the page layout. To see how other elements on the page are being affected during your animation, the browser completely recalculates your page's layout.

For every. single. frame.

This is where the CSS transform property comes in. transform causes your element to be animated like an image, and avoids all the layout recalculations. If you can use this approach, you should.

Unfortunately there are two deal-breakers in using transform to collapse your content:

  1. The content warps when it collapses.
  2. It leaves a gap where the content was.

Method 2: Animate max-height / max-width

Instead of animating on height, a different approach is to set a fixed (and large) max-height and then transition that to 0px.

The upside of this approach is that it's straightforward. It also manages to avoid the weird warping effect of transform: scale.

There are some downsides, though:

Method 3: Calculate height with JavaScript

A lengthier (but more precise) approach is to use JavaScript to calculate the animation start and end using the element's rendered height.

Once we determine the element's actual height, we add it to the element's inline styles to give the animation something to transition between.

In terms of effect, this is probably the one you were going for. Here are the downsides:

Method 4: Nuke from orbit with FLIP + Inverse Scaling

Remember Method 1 and all the problems that using transform caused?

Well, it turns out you can fix them. To address content warping, you can apply scaling in the other direction. You can also use the FLIP technique to move surrounding content in a performant way.

The scaling works by calculating our start and end sizes and interpolating the scaling values into two animations that cancel out each other's scaling effects.

We also calculate the end position of the sibling elements and apply a transition to move them there while the scaling animation is happening.

This looks much better than our initial transform attempt, and solves the problems we were having. However:

Can't get past JavaScript Tutorials?

Download my FREE ebook on how to succeed as a self-taught JavaScript Developer, and how to find projects that you'll actually finish. Learn More...

Share this: