Togglable content using interpolate-size

If you've done frontend for a while you were probably given a task where an element should expand at a click and show it's content. You usually see thees kind of features in accordions, FAQs, filters and so on. Normally in CSS there is no problem animating numeric values, but animating keyword values is different.
Lengthy introduction (optional)
Let's start with an example. We were asked to create a simple box that consist of a header that you can click and expand some long text - business will use it for Q&A section. Okay, it's seems easy - let's go.
All we need to do is to switch value of height
of content box from 0
when it's collapsed to auto
when it's visible. Right? It makes sense.
Basic implementation would look like this:
.expandable__content {
height: auto;
overflow: hidden;
transition: height 300ms ease;
}
.expandable__content--hidden {
height: 0;
}
...aaaaand it doesn't work.
This is the whole problem with transitioning and animating keyword values like auto
. This type of values are called intrinsic values which pretty much means based on content dimensions and for long time we could now do anything about it, so above example wouldn't work, despite that it seems the most sensible.
You could simply add some fixed up value for height
like 500px and call it a day, but it would mean that the container is always fixed at with this height even when content doesn't take the whole space.
Nowadays, in most cases you would rather take a different approach. Intead of transitioning height
you go with max-height
and give it some arbitrary, large number like 100vh. This property makes sure there is now redundant space in the container.
.expandable__content {
max-height: 100vh;
overflow: hidden;
transition: max-height 300ms ease;
}
.expandable__content--hidden {
max-height: 0;
}
I'll be honest. Despite me using this method for years now and always working for me fine, I've always found it approach stinky. The idea of putting an arbitrary numeric value seems just... off. And there is actually a couple of drawbacks it may lead to occure.
First of all - the animation. You may or may not have noticed, but in this method there is a slight delay before the animation triggers and the delay actually depends on the arbitrary value. That's because the animation simulates the content to be of height equal to arbitrary value you have given so most likely more than the content itself. This extends animation significantly making it not seem to be working according to your timing curve.
Second - content may get cut off at times. Since we applied a fixed up value to the container height and overflow of some kind then it may cut off some content when viewport height is very small.
interpolate-size: allow-keywords
And this is where interpolate-size
shines. It's a way of allowing us to animate or transition property values that are considered intrinsic size like auto
in our case. Normally, keyword values (auto
, max-content
, initial
, etc.) cannot be animated, only numeric values can (px
, rem
, etc.).
There are two values it can take:
numeric-only
- this means the numeric intrinsic values cannot be animated, which is the default behavior.allow-keywords
- this allows keywords likeauto
,max-content
,min-content
, etc. to be animated or transitioned.
So let's go back to our example. Now the basic code would look like this:
.expandable__content {
interpolate-size: allow-keywords;
height: auto;
overflow: hidden;
transition: height 300ms ease;
}
.expandable__content--hidden {
height: 0;
}
This is pretty much the first example that seemed the most sensible, but with interpolate-size: allow-keywords;
added. Now our height of intrinsic value will be animated nicely. The animation delay is also correct, different from what we've seen in the max-height: 100vh
example above.
Browser Support
Intrinsic-size
has not yet been supported by all browsers. In fact, at the moment of writing this article (late 2024), it's only supported by Chrome and (surprisingly) Edge, resulting in covering 67% of internet browser traffic.
Although the feature seems exceptionally useful, we still have to wait for more support. At this point, I would rate this feature as experimental and I discourage implementing it in a production environment.
You can look up current support at caniuse.com.
External Resources:
- MDN article on interpolate-size - https://developer.mozilla.org/en-US/docs/Web/CSS/interpolate-size
- GitHub thread proposing animating keywords for
height
- https://github.com/w3c/csswg-drafts/issues/626