Animating Indefinite Dimensions with CSS3

If you, like many, have started using CSS3 transitions to create slick, simple animations in your app then you might have noticed a problem when trying to animate properties such as width and height: they only work with specific values.

While this isn't always an issue, if you're trying to build something like a collapsible content block it can be a big problem: your content is variable height, so you can't set a specific value on it. I was running into this particular wall yesterday and so put it out to Twitter. I got this in response:

@mbleigh maybe try animating max-height

— Andy Ogzewalla (@andyogzewalla) June 21, 2012

A ha! There's a clever idea for a workaround. Rather than animate the property that we don't/can't know in advance, we'll animate the max-height property instead. But does it work? Yes! Well, yes with a but. The animation works fine but it will not be the exact length you expect: if your content is 100px tall and you animate the max height to 200px the animation will execute in half the time. This can also mess with easing functions so isn't a perfect solution.

Performing the Animation

So how do we set this up? Let's take a simple "collapsible content block" example. Here's a simple example of how to do it:

http://jsfiddle.net/mbleigh/fsrGk/embedded/

Pixel Perfect

So what if we want to make our animations pixel-perfect? Well, unfortunately we're going to have to rely on Javascript. When the page loads we will need to iterate through all collapsibles and set the height of each one to its automatically determined height. We will also need to change the animations to height instead of max-height and set the !important flag on the zero height. Here's the result:

http://jsfiddle.net/mbleigh/f6Xby/embedded/

Note that this implementation requires that we re-calculate the height if the content inside the collapsible changes at any point. This brittleness is the main reason that, even though the animation is smoother, I'm tempted to use the max-height trick. It requires less intrusive Javascript and can continue to work even if the content changes.