Animate height: auto in CSS with interpolate-size

Smooth height auto animations without JavaScript

Animating to height: auto required JS to measure scrollHeight, set a fixed pixel height, then snap back to auto. interpolate-size: allow-keywords lets CSS transition directly to and from intrinsic sizes.

Old way10 lines
.accordion  {  overflow: hidden;}// JS: measure, set px height, then snap to autofunction open(el) {   el.style.height = el.scrollHeight + 'px';   el.addEventListener('transitionend', () => {     el.style.height = 'auto';   }, { once: true }); }
Modern
6 lines
:root   {  interpolate-size: allow-keywords;}.accordion   {  height: 0;  overflow: hidden;  transition: height .3s ease;}.accordion.open   {  height: auto;}
Limited availability69% global usage

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Not ready for production without a fallback.

129+
129+
click to expand with height: auto animation
What is oklch?

oklch(L C H) is a perceptually uniform color space. L is lightness, C is chroma (saturation), H is hue angle. Equal L values look equally bright regardless of hue.

Why not HSL?

HSL lightness is not perceptually uniform. Yellow at 50% L looks far brighter than blue at 50% L. oklch fixes this by modeling how human vision actually works.

Browser support

oklch is supported in Chrome 111+, Firefox 113+, and Safari 15.4+. Over 90% global coverage.

No JS needed

No scrollHeight measurement, no transitionend listener, no pixel-to-auto snap.

Works with any keyword

Transitions to and from auto, min-content, max-content, and fit-content all work with one declaration.

Set it once

Declaring interpolate-size on :root unlocks keyword size transitions everywhere on the page.

Lines Saved
10 → 6
No JS height measurement
Old Approach
scrollHeight + JS
Measure, set px, then snap to auto
Modern Approach
interpolate-size
Transition to height: auto directly

How it works

height: auto isn't animatable because the browser can't interpolate between a fixed length and a keyword. The workaround was JavaScript: read scrollHeight to get the actual pixel height, set it as a fixed value, trigger the transition, then snap back to auto on transitionend.

interpolate-size: allow-keywords opts the browser into animating keyword sizes. Set it on :root once and transitions to height: auto, width: fit-content, and other intrinsic sizes work everywhere on the page. No JavaScript, no scrollHeight, no transitionend.

ESC