I know this is something Chris wanted foreverso it is no surprise that he already has a fantastic article just a day after the news broke. In fact, I only found out about it through his post and couldn’t dig up an announcement. So I thought I’d take some notes because it feels like a significant development.
The news: Transition to auto is now a thing! Well, it’s coming. Chrome Canary recently shipped support for it and that’s the only place you’ll find it right now. And even then, we just don’t know if the Chrome Canary implementation will find its way into the syntax when the feature becomes official.
The problem
Here’s the situation. You have an element. You’ve selected it, inserted content, and applied a bunch of styles to it. Do you know how big it is? Of course not! Of course we can ask JavaScript to evaluate the element for us, but as far as CSS is concerned, the calculated dimensions of the element are unknown.
This makes it difficult to animate this element, for example. height: 0 To height: whatever. We need to know what “whatever” is, and the only way we can do that is by setting a fixed height for the element. That way we have numbers that go from zero height to that specific height.
But what happens if that element changes over time? Maybe the font changes, we add padding, more content is inserted… anything that changes the dimensions. We’ll probably need to update that height: 300px to the new fixed height that works best. This is why JavaScript is often used to toggle things that expand or shrink in size, among other workarounds.
I say it is about the height property, but we also talk about the logical equivalent, block-sizeas well as width And inline-size. Or any direction at all!
Transition to auto
That is the goal, isn’t it? We tend to reach for height: auto if the height dimension is unknown. From there, we let JavaScript calculate what the result is and go from there.
The current Chrome implementation uses CSS calc-size() to do the hard work. It recognizes the auto keyword and, true to its name, calculates this number. In other words, instead of the fixed height approach, we can do this:
It really is! Of course, calc-size() is capable of handling more complex expressions, but the fact that we can give it just a vague keyword about the height of an element is pretty damn impressive. This allows us to go from a fixed value to the intrinsic size of the element and back.
I had to try it out. I’m sure there are a ton of use cases here, but I decided to use a floating button in a calendar component that displays a certain number of pending calendar invitations. Click the button and a window expands above the calendar to display the invitations. Click it again and the window goes back to where it came from. JavaScript handles the click interaction and triggers a class change that changes the height in CSS.
When clicked, JavaScript sets the element’s auto-height as an inline style to override the CSS:
The transition Property in CSS tells the browser that we plan to height property at a certain point, and to make it smooth. And as with any transition or animation, it is a good idea to take motion sensitivities into account by Slowing down or removing movement with prefers-reduced-motion.
How about display: none?
This is one of the first questions that came to my mind when I read Chris’ post, and he addresses it. The transition from one element to display: none to its intrinsic size is a kind like height: 0. It may look like an undisplayed element has a height of zero, but it actually has a calculated height of auto unless a specific amount is specified.
So there is additional work to be done as we transition from display: none in CSS. I’ll just paste the code Chris shared because it demonstrates the most important parts well:
The element begins with both display: none And height: 0.
There is a .open Class that sets the height of the element to calc-size(auto).
These are the two points that we need to connect. To do this, we first set transition-behavior: allow-discrete on the element. This is new to me, but the specification says The transition-behavior “indicates whether transitions for discrete properties are started or not.” And if we declare allow-discrete“Transitions are initiated for both discrete and interpolable properties.”
Well, DevTools showed us right there that height: auto is a discrete property! Note the @starting-style Declaration. If you are not familiar with this, you are not alone. The idea is that it allows us to specify a style for a transition to “start” with. And since the discrete height of our element autowe must instruct the transition to height: 0 instead: