CSS interpolate-size: Animate From 0 to auto

An expanding panel knows its natural height. CSS traditionally could not animate to it, which is why such a small interaction produced so many max-height tricks and JavaScript measurements.

This looks like it should work:

.panel {
  height: 0;
  transition: height 300ms;
}

.panel.open {
  height: auto;
}

But browsers traditionally could not smoothly animate between 0 and auto.

Developers worked around it with JavaScript, large max-height values, or transforms.

The newer interpolate-size property is designed to solve this.

There is one important warning: browser support is still not complete everywhere in 2026, so I would use it as progressive enhancement rather than making an important interface depend on it.

Why height: auto did not animate

Imagine an expandable section:

<div class="panel">
  <p>
    This content can be short or long.
  </p>
</div>

You do not know the exact height because the content can change.

That is why auto is useful.

Historically:

0px → 200px

was easy to animate.

0px → auto

was not.

The new approach

You can allow intrinsic sizes to be interpolated:

:root {
  interpolate-size: allow-keywords;
}

Then:

.panel {
  height: 0;
  overflow: hidden;
  transition: height 300ms ease;
}

.panel.open {
  height: auto;
}

In supporting browsers, the browser can animate between the numeric height and the natural auto size.

Why set it on :root?

interpolate-size is inherited.

You can enable it once:

:root {
  interpolate-size: allow-keywords;
}

or only for one component:

.accordion {
  interpolate-size: allow-keywords;
}

The old max-height trick

A common workaround is:

.panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 300ms;
}

.panel.open {
  max-height: 1000px;
}

It works, but 1000px is just a guess.

If the content is taller, it breaks. If the content is much shorter, the timing can feel strange.

The browser is technically animating toward 1000 pixels even when the real content is only 180 pixels tall.

The JavaScript workaround

Another method measures the element:

panel.style.height = `${panel.scrollHeight}px`;

This works, but JavaScript now needs to measure layout and keep track of size changes.

If CSS can animate to the natural size directly, there is less code.

Use <details> when possible

Before building a custom accordion, ask whether HTML already has what you need:

<details>
  <summary>More information</summary>
  <p>Content goes here.</p>
</details>

For a normal FAQ or disclosure section, <details> is often the better starting point.

interpolate-size is more interesting for custom components and layout transitions.

A safe fallback

Because support is still limited, keep the base experience working.

.panel {
  height: auto;
}

@supports (interpolate-size: allow-keywords) {
  .panel {
    height: 0;
    overflow: clip;
    transition: height 250ms;
    interpolate-size: allow-keywords;
  }

  .panel.open {
    height: auto;
  }
}

In an older browser, the content simply remains visible.

That is not the exact same design, but it remains usable.

Respect reduced motion

@media (prefers-reduced-motion: reduce) {
  .panel {
    transition: none;
  }
}

This is a good habit for any motion added only for visual polish.

Where it can help

Good uses include:

I would not use it only because it is new.

The best use is when it lets you remove a brittle workaround.

Progressive enhancement is the right fit

interpolate-size is a good example of modern CSS that can be added without harming older browsers.

The base interface works.

Newer browsers get a smoother transition.

Older browsers still get the content.

I would use this as progressive enhancement: keep the content and open state working everywhere, then add the smoother size transition where supported. An animation is not worth making the component depend on it.