Animating to or from height: auto has been something front-end developers have had on their wishlist for a very long time, and now, not only can we do that very easily, but there are new possibilities that have opened up on top of that as well, all thanks to two new CSS features:
- The interpolate-size property
- The
calc-size()
value function
All you need is one line of CSS
#The new interpolate-size
property enables animating to intrinsic sizes, such as auto
.
Here’s a simple example of it in action: We go from block-size: 1lh
to block-size: auto
.
Enabling it site-wide with a single declaration
#The value of interpolate-size
is inherited, so we can enable it across our entire site with a single declaration.
html {
interpolate-size: allow-keywords;
}
That means with a single declaration, you’ve basically opted in to allow transitions and animations using keyword values site-wide!
This is perfect to include this as part of your CSS reset for new projects.
I’ve already started using this in a few places where I need to go from block-size: 0
to block-size: auto
, such as with navigations and menus.
We can also use this to animate details/summarys, though that also involves using ::details-content
, which at the time of writing, has very limited support. Just like calc-size()
and interpolate-size
, it does make for a great progressive enhancement!
It’s not just for height auto
#While animating to and from height: auto
might be the most common pain point interpolate-size
solves, it also allows us to animate to any of these keyword values:
- auto
- min-content
- fit-content
- max-content
- content
However, you cannot use this to go between two different keyword values, as you can see in this example where it doesn’t work.
While that would be cool, I still see this as such a big win that I really don’t mind this one constraint.
You can use animations as well
#All of the examples so far have used transitions, but this also opens up using keyword values in animations as well.
For example, instead of simply transitioning open to closed, we can add a nice little bounce effect.
Why isn’t this the new default?
#There were talks of having this be the default value, but there would be potential conflicts in older sites, such as situations where JavaScript was being used for these types of animations or where assumptions were made knowing transitions wouldn’t work in specific situations.
Because of this, I’d caution against blindly inserting this into older projects. From now on, throw it in that reset and make animations super easy, but I wouldn’t retrofit it into an old project without some testing first.
When you need more fine-grained control
#interpolate-size
is such a quick win, but you might find yourself running into situations where you want something a little bit bigger or smaller than one of the intrinsic sizes.
calc()
doesn’t allow for calculations based on keyword values, but another new addition is calc-size()
, which does!
The syntax of calc-size()
is a little trickier than that of calc()
, but once you get used to it, it’s not so bad.
The reason I say that it’s trickier is that you must pass two values:
- the intrinsic value that you want to use
- the calculation you want to do to that size
Here are some examples:
.height-example {
block-size: calc-size(auto, size + 24px)
}
.width-example {
inline-size: calc-size(max-content, size * .5);
}
In the first example above, I pass the keyword value that I want to do the calculation on (auto
), and then after the comma, I say to take whatever size value is computed and add 24px
to it.
In the second example, I want the calculation to be based on the max-content
of my element and then multiplied by 0.5
so that it becomes half that size.
Here is another simple example.
.max-content {
inline-size: max-content;
}
.bit-bigger-than-max-context {
inline-size: calc-size(max-content, size + 3rem);
}
For a bit more of a practical use case, in the example below, I use position absolute to move an SVG icon out of the flow and offset it to overflow to the right of the button that it is inside of. Then, using calc-size()
for the hover and focus states, I can add the distance I’ve offset the icon to the auto size of my button.
Animations and transitions with calc-size()
#While you might want to use calc-size()
for making something slightly bigger or smaller than one of the keyword values, just like interpolate-size, it also opens up animations and transitions on these values as well.
Below, I’ve updated the previous example to add a transition to the inline-size
of my button. Because I’m using a calc size()
, it works!
calc-size() doesn’t require interpolate-size
#When you use calc-size()
, transitions to and from intrinsic sizes will be allowed regardless of whether you’ve declared interpolate-size: allow-keywords
.
You can see that in action in the previous example, where I didn’t declare interpolate-size
, and the transition still works.
That means that you could do something like this all on its own, and it’ll work as well:
.transition-height {
height: 1.5lh;
overflow: clip;
transition: height 1s;
}
.transition-height:hover {
height: calc-size(auto, size);
}
However, it is recommended to use interpolate-size
for this instead.
It’s easier to simply “turn on” site-wide keyword animations and transitions and then rely on calc-size()
when you need to do actual calculations based on keyword values.
Also, it’s worth noting that, just like interpoloate-size: allow-keywords
doesn’t work for transtions or animations between keyword values, the same holds true with calc-size()
.
Using interpolate-size as a progressive enhancement
#If interpolate-size is not supported by a browser and you go from block-size: 0
to block-size: auto
, the browser will still switch between those two sizes, just without the transition between them. And to me, that makes it a perfect progressive enhancement.
People who are using browsers that support it get a nicer experience, but it won’t cause any issues for anyone using a browser that lacks support.
On the other hand, calc-size()
might be something you have to be more careful with, though.
For my buttons above, where I expanded them to show an icon, I wouldn’t really mind if a user didn’t see the icon because it doesn’t give extra value or context to the purpose of the button, but there are times when the extra size you are adding could be important or impact the layout in an important way.
In either case, it probably is a bit of a case-by-case basis, but I do think most cases of interpolate-size
would be fine. You might either have to think about it or provide alternatives with a @supports
feature query for calc-size()
.
Kevin selected CHU Sainte-Justine Foundation for an honorary donation of $50
Support CHU Sainte-Justine in its pursuit of excellence and its commitment to providing children and mothers with one of the highest levels of health care in the world, now and in the future.