CSS interpolate-size: Animate height: auto with a Fallback
height: auto used to be the awkward edge of CSS transitions: a browser could animate between two numeric lengths, but not calculate the content’s intrinsic end size during the transition. The interpolate-size property lets you opt into a length-to-keyword interpolation, so a panel can move from height: 0 to height: auto without measuring itself in JavaScript.
Support is still not universal. MDN labels interpolate-size limited availability and not Baseline, so the production pattern needs a fallback rather than a browser-version assumption.
Opt in at the narrowest useful scope
The property is inherited. Set it at :root when the design system intentionally wants intrinsic-size animations, or on the component container when only one interaction needs the behavior:
:root { interpolate-size: allow-keywords;}The default is numeric-only. allow-keywords permits a numeric length or percentage to interpolate with supported intrinsic keywords such as auto, min-content, max-content, and fit-content. It does not make every pair of intrinsic keywords interpolable.
Animate a content panel
Use a real state attribute that your component code updates alongside aria-expanded or the appropriate semantic state. The CSS below uses data-open so it can be adapted to a disclosure, accordion, or navigation panel:
.panel { height: auto; max-height: 0; overflow: hidden; transition: max-height 250ms ease;}
.panel[data-open='true'] { max-height: 40rem;}
@supports (interpolate-size: allow-keywords) { .panel { height: 0; max-height: none; overflow: clip; transition: height 250ms ease; }
.panel[data-open='true'] { height: auto; }}
@media (prefers-reduced-motion: reduce) { .panel { transition-duration: 0s; }}The fallback uses a max-height ceiling, so choose a value that safely contains the component’s expected content. It is a graceful visual fallback, not an invitation to hide arbitrarily large content. If the panel can grow without a reasonable ceiling, use a measured height in the unsupported path or accept an instant open/close.
The supported path transitions from the numeric 0 to the intrinsic auto keyword. Keep the panel in the layout while it transitions; applying the HTML hidden attribute at the same moment sets display: none and removes the transition opportunity. Your interaction code still needs to manage focus, keyboard behavior, and accessible state.
Use calc-size() for a calculated intrinsic end
If the open state needs a small amount of extra space, calc-size() can combine an intrinsic size with a calculation:
@supports (height: calc-size(auto, size + 1rem)) { .panel[data-open='true'] { height: calc-size(auto, size + 1rem); }}You do not need calc-size() for the basic 0 to auto transition. Start with interpolate-size; reach for calc-size() when the final size really needs a calculation. Both features should keep the same fallback behavior for browsers that do not support them.
Know the interpolation boundary
The property allows one <length-percentage> endpoint and one supported intrinsic keyword endpoint. These are reasonable pairs:
.card { interpolate-size: allow-keywords; height: 12rem;}
.card[data-expanded='true'] { height: auto;}These are not magically solved by the property:
autotomax-content, because both endpoints are intrinsic keywords- an unsupported keyword in the browser you are testing
- content that is removed from layout before the transition starts
- an interaction that needs JavaScript to coordinate measurement, focus, or asynchronous content
Check the MDN interpolate-size reference for the current compatibility table and the Chrome explanation of animating to height auto for the underlying model.
Treat accessibility as a separate requirement
CSS only animates the box. A disclosure button should expose its state with aria-expanded, reference the panel with aria-controls, and keep focus behavior predictable. Do not use a visual height animation to replace semantic HTML or to make a panel permanently invisible to keyboard and assistive-technology users.
Test at least these states:
- Open and close with a pointer and keyboard.
- Tab into the content while it is open.
- Resize the viewport so the content needs more than the fallback ceiling.
- Enable reduced motion and confirm the state still changes immediately.
- Test an unsupported browser to make sure content remains usable without the transition.
If you are already using intrinsic sizing for form controls, the CSS field-sizing: content guide covers the related progressive-enhancement pattern. field-sizing changes preferred control size; interpolate-size controls how a supported size transition is calculated.
FAQ
Does interpolate-size animate auto to auto?
No. It enables interpolation between a numeric length or percentage and a supported intrinsic keyword. Two intrinsic keywords still do not form a generally interpolable pair.
Do I still need JavaScript?
Not necessarily for the height measurement itself in supported browsers. You still need interaction logic for state, semantics, focus, and any fallback that needs a measured ceiling.
Is height: auto animation safe to ship?
Ship it as progressive enhancement. Keep an @supports fallback and test the browsers, content sizes, and reduced-motion behavior that your site supports.
References:
Report a typo or broken link, or suggest a related topic.