CSS interpolate-size: Animate From 0 to auto

Animating an element from closed to its natural height has been awkward for years.

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.

The problem

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.

That is a much better approach than making the whole component depend on a feature that some visitors may not have yet.