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 want | say |
|---|---|
| a section must grow to fit content without a magic pixel value | height animation |
| content should be uncovered rather than moved in | reveal animation |
| a layout change must animate without animating layout properties | flip |
Related
See also: Interpolation · Accordion