CSS calc-size(): Math on auto and fit-content
Intrinsic size math without guessing pixel heights
calc() cannot use auto or fit-content. calc-size() can, so you can do fit-content * 0.7 or auto + 2rem, and animate to those values without JavaScript height measurement.
The old hack vs the modern fix
View democonst drawer = document.querySelector('.drawer');
drawer.addEventListener('mouseenter', () => {
drawer.style.height = drawer.scrollHeight + 16 + 'px';
});
drawer.addEventListener('mouseleave', () => {
drawer.style.height = '2.5rem';
});.drawer {
height: 2.5rem;
overflow: hidden;
transition: height .4s ease;
}
.drawer:hover,
.drawer:focus-within {
height: calc-size(max-content, size + 1rem);
}
/* intrinsic end state + extra space, no scrollHeight */Calc size browser support
calc-size() ships in Chrome and Edge 129+. Firefox and Safari have no support yet. Prefer interpolate-size for plain auto animations, and keep a scrollHeight fallback where you need intrinsic math today.
Live demo
Why the modern way wins
Math on keywords
calc() rejects auto and fit-content. calc-size() treats them as a size basis you can add to or scale.
Animatable return values
Using calc-size() opts the value into keyword interpolation, so transitions to modified intrinsic sizes work.
When to prefer interpolate-size
If you only need height: auto with no math, set interpolate-size: allow-keywords instead. Reach for calc-size() when the end state needs a calculation.
- Old Approach
- scrollHeight + fixed px
- Measure, set, snap back
- Modern Approach
- calc-size()
- Intrinsic size + expression
How it works
calc-size(basis, expression) takes an intrinsic size as the first argument and a math expression as the second. Inside the expression, the keyword size stands for that basis. So calc-size(fit-content, size * 0.7) is seventy percent of fit-content, and calc-size(max-content, size + 1rem) is max-content plus a rem.
Return values interpolate, which means you can transition from a fixed height to a calculated intrinsic size. That is the case interpolate-size alone cannot cover: animating between an intrinsic size and a modified version of the same intrinsic size.
Firefox and Safari do not support calc-size() yet. Until they ship it, keep measuring with JavaScript for those browsers, or stick to plain interpolate-size animations that do not need math.