{"id":252477,"date":"2017-03-10T06:47:39","date_gmt":"2017-03-10T13:47:39","guid":{"rendered":"http:\/\/css-tricks.com\/?p=252477"},"modified":"2021-04-03T13:47:00","modified_gmt":"2021-04-03T20:47:00","slug":"using-css-transitions-auto-dimensions","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/using-css-transitions-auto-dimensions\/","title":{"rendered":"Using CSS Transitions on Auto Dimensions"},"content":{"rendered":"\n

We’ve all been there. You’ve got an element you want to be able to collapse and expand smoothly using CSS transitions, but its expanded size needs to be content-dependent. You’ve set transition: height 0.2s ease-out<\/code>. You’ve created a collapsed<\/code> CSS class that applies height: 0<\/code>. You try it out, and… the height doesn’t transition. It snaps between the two sizes as if transition<\/code> had never been set. After some fiddling, you figure out that this problem only happens when the height starts out or ends up as auto<\/code>. Percentages, pixel values, any absolute units work as expected. But all of those require hard coding a specific height beforehand, rather than allowing it to naturally result from the size of the element content.<\/p>\n\n\n\n\n\n\n\n

\"\"
Nikita Vasilyev documented this well<\/a>.<\/figcaption><\/figure>\n\n\n\n

In this article, I mostly speak in terms of height<\/code> for simplicity, but everything here also applies to width<\/code>.<\/p>\n\n\n\n

If you were hoping I had a magical, complete solution to this problem, I’m sorry to disappoint you. There’s no one solution that achieves the desired effect without downsides. There are, however, multiple workarounds that each come with a different set of advantages and disadvantages, and in most use cases at least one of them will get the job done in an acceptable manner. I’ll outline the major ones, and list out their ups and downs so you can hopefully pick the best one for your situation.<\/p>\n\n\n

Why hasn’t this problem been fixed at the browser level?<\/h3>\n\n\n

According to the Mozilla Developer Network docs, auto values have been intentionally excluded from the CSS transitions spec<\/a>. It looks like it’s been requested by a few people<\/a>, but when you think about it, it makes at least a little sense that it hasn’t been included. The browser process that re-calculates the sizes and positions of all elements based on their content and the way they interact with each other (known as “reflow”) is expensive<\/a>. If you were to transition an element into a height<\/code> of auto<\/code>, the browser would have to perform a reflow for every stage of that animation, to determine how all the other elements should move. This couldn’t be cached or calculated in a simple way, since it doesn’t know the starting and\/or ending values until the moment the transition happens. This would significantly complicate the math that has to be done under the hood and probably degrade performance in a way that might not be obvious to the developer.<\/p>\n\n\n

Technique 1: max-height<\/code><\/h3>\n\n\n

If you web search this problem, the max-height<\/code> approach will probably be mentioned in all of the first five to ten results. It’s actually pretty unideal, but I thought it was worth including here for the sake of comparison.<\/p>\n\n\n\n

It works like this: CSS values can only be transitioned to and from fixed unit values. But imagine we have an element whose height<\/code> is set to auto<\/code>, but whose max-height<\/code> is set to a fixed value; say, 1000px<\/code>. We can’t transition height<\/code>, but we can<\/em> transition max-height<\/code>, since it has an explicit value. At any given moment, the actual height of the element will be the minimum of the height<\/code> and the max-height<\/code>. So as long as max-height<\/code>‘s value is greater than what auto<\/code> comes out to, we can just transition max-height<\/code> and achieve a version of the desired effect.<\/p>\n\n\n\n