vocab.design

motion · web-platform

Height animation

also called animate to height auto (chrome-developers), collapse animation (community), accordion animation (community), auto-height transition (community), interpolate-size (css), calc-size (css)

Animating a container between collapsed and its content's natural size, long impossible because height auto did not interpolate and now opened up by interpolate-size and calc-size().

Every accordion, every disclosure, and every expanding row wants the same thing: grow from nothing to exactly as tall as the content, smoothly. For most of the web’s life that was the one animation CSS would not do. A transition interpolates between two values, and auto is not a value: it is an instruction to work the height out during layout, so the browser has no number to start from and nothing to divide the duration between. The height therefore snapped, and everyone reached for a workaround instead.

There were three, and each cost something. Transitioning max-height from zero to a generously large guess works, but the guess is what you pay: the visible growth stops when the content ends while the transition keeps running to the guessed value, so the panel appears to finish early on short content and the easing curve stops meaning anything. Measuring the content in JavaScript and setting a pixel height is accurate, but it has to be redone whenever the content, the width, or the font changes, and it drags a layout read into every open. The grid trick, animating a single row between grid-template-rows: 0fr and 1fr, is the cleanest of the three and needs no script at all, though it costs a wrapper element and an overflow: hidden that surprises anything trying to escape the box.

The platform fix arrived as two pieces. interpolate-size: allow-keywords, usually set on the root, tells the browser it may interpolate intrinsic sizes, after which a plain height: auto transition animates. calc-size() is the finer instrument: it makes an intrinsic keyword usable in arithmetic, so calc-size(auto, size + 1rem) or a transition between calc-size(auto) and a fixed value both become expressible. Opting in explicitly is the design here rather than an accident, because making auto animate everywhere by default would change how existing pages behave. The same family of additions covers the neighbouring problem, where transition-behavior: allow-discrete lets an element transition while display is changing.

Two details survive whichever spelling is used. Give the container overflow: hidden for the duration, or the content spills out of a box that is shorter than it is, and hand the height back to auto once the transition ends so that later content changes are not trapped inside a stale pixel value. Fade the content slightly behind the box rather than with it, since text arriving at full opacity in a half-open panel is the part that reads as jumpy. And under a stated prefers-reduced-motion let the panel simply be open: the size change carried no information the panel’s own presence did not.

Which word?

If you wantsay
a section must grow to fit content without a magic pixel valueheight animation
content should be uncovered rather than moved inreveal animation
a layout change must animate without animating layout propertiesflip

Related

See also: Interpolation · Accordion

Sources