Front end

How to animate to auto in CSS

Animating to auto used to be impossible until CSS fixed it!

2 minute read Front end Craig Buckler

Animating to auto is one of those CSS features every frontend developer tries. The typical use-case is an expanding box which animates from a fixed height of, say, 20px to the height of it's content -- or auto. Any attempt results in frustration because the animation won't work.

Of course, the browser knows the actual height of the box, but mathematically interpolating 20px to auto is not possible in CSS. Until now.

The interpolate-size CSS property

The new interpolate-size: allow-keywords; CSS property enables resizing between any intrinsic size value such as auto, fit-content, min-content, or max-content. The following demonstration shows the default behaviour, but clicking the checkbox enables a smooth animation:

<iframe src="./demo.html" width="600" height="600"></iframe>

The essential CSS:

div {
  block-size: 4lh;
  overflow: clip;
  interpolate-size: allow-keywords;
  transition: block-size 1s ease-in-out;
}

div:hover {
  block-size: auto;
}

interpolate-size: allow-keywords; is available in Chromium-based browsers including Chrome, Edge, Opera, Vivaldi, and Brave. It's coming to other browsers but this is a perfect example of progressive enhancement: without support, the box still expands -- it just won't be animated.

By default, the browser applies the standard non-animating behaviour interpolate-size: numeric-only; to all elements. You can apply interpolate-size: allow-keywords; to specific elements or all elements with:

:root {
  interpolate-size: allow-keywords;
}

The calc-size() CSS function

Sometimes, animating to auto is not quite what you need. Assume you want to animate to half the box's height. The following CSS won't work because calc() does not support intrinsic size keywords such as auto:

/* FAILS! */
div:hover {
  block-size: calc( auto / 2 );
}

The calc-size() function fixes the problem:

/* WORKS! */
div:hover {
  block-size: calc-size( auto, size / 2 );
}

You pass it two parameters:

  1. a value -- typically an intrinsic size keyword such as auto, and
  2. an expression calculation where size denotes the value passed.

Other examples:

/* auto plus an extra 2em */
block-size: calc-size( auto, size + 2em );

/* auto rounded up to nearest 50px */
block-size: calc-size( auto, round(up, size, 50px) );

Again, calc-size() is only available in Chromium-based browsers at this time. Other browsers won't parse the function so ensure you define a fallback:

div:hover {
  /* fallback size */
  block-size: auto;

  /* larger size where supported */
  block-size: calc-size( auto, size + 2em );
}

Documentation

For more information, refer to MDN:

Ready to build?

Have something complicated to build?

Tell us what you are trying to achieve, not just which page template you think you need. Whether it is a bespoke web application, a complex ecommerce build, or ongoing development support — we will tell you honestly how we can help.