740 words
4 minutes

CSS interpolate-size: Animate height: auto with a Fallback

2026-08-07
Frontend
CSS
/
HTML
/
Animation
/
Progressive Enhancement

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:

  • auto to max-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:

  1. Open and close with a pointer and keyboard.
  2. Tab into the content while it is open.
  3. Resize the viewport so the content needs more than the fallback ceiling.
  4. Enable reduced motion and confirm the state still changes immediately.
  5. 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:

MDN interpolate-size reference

Chrome: Animate to height auto

CSS interpolate-size: Animate height: auto with a Fallback
https://laplusda.com/en/posts/css-interpolate-size-height-auto/
Author
Zero
Published at
2026-08-07
License
CC BY-NC-SA 4.0
Was this article useful?

Report a typo or broken link, or suggest a related topic.