interpolate-size
Animating an element from a fixed height to auto has been impossible in CSS for decades. The browser cannot
interpolate between a concrete value and a keyword it has not yet computed.
interpolate-size: allow-keywords changes that, enabling smooth height transitions on accordions,
disclosures, and any element that needs to expand to fit its content.
What is interpolate-size?
interpolate-size allows CSS to animate between a fixed height and
height: auto, something that was impossible for decades, as the browser simply could not
resolve size keywords to concrete values. Browsers had no midpoint to interpolate. Some developers used to
animate max-height to a large arbitrary value as a workaround, but that caused the element to reach its
final size before the transition ended, making the easing feel wrong, as well as clamping content if the max
value was ever bypassed. That method is outdated. A javascript approach works, but adds overhead and
complexity to something that should be handled by pure CSS.
How does interpolate-size work?
Setting interpolate-size: allow-keywords on :root opts the entire page into
keyword interpolation. By adding that single line, the browser will treatt size keywords like auto, min,
max, ect. as animatable endpoints. Applying it to :root is recommended, which can be done on
your base elements.css file. Correct implementation typically looks like the following:
:root {
interpolate-size: allow-keywords;
}
Usage Pattern
With interpolate-size: allow-keywords set on :root, a height transition set to
auto works exactly as expected. The overflow: hidden is required to clip the
content during transition, as without it the content would become suddenly fully visible during animation.
This panel is intentionally broken, using overflow: visible; instead to demonstrate that
failure.
Additionally, for accessibility, you should always opt-in to the users preferences for reducing-motion. A good format for a block of code utilizing interpolated transitions might look something like this:
.panel {
height: 0;
overflow: hidden;
transition: height 0.35s ease;
}
details[open] .panel {
height: auto;
}
@media (prefers-reduced-motion: reduce) {
.panel {
transition: none;
}
}
Browser Support
This one intentionally doesn't work, showing what it looks like on a browser that doesn't support it. The interpolate-size progressive enhancement is fully supported in Edge and Chrome, but not yet supported in firefox or safari, but it should be treated as an easy addition that enhances HTML wherever its supported and works natively without JavaScript. In unsupported browsers, it fails gracefully, by just not animating. However, If you need it to animate anyway, you can force it to animate by using the following javascript:
if (!CSS.supports('interpolate-size', 'allow-keywords')) {
document.querySelectorAll('details').forEach((details) => {
const panel = details.querySelector('.panel');
details.addEventListener('toggle', () => {
panel.style.height = details.open
? panel.scrollHeight + 'px'
: '0';
});
});
}