🧙‍♂️ CSS trick: transition from height 0 to auto!
Tags: webdev, frontend, css
Published: 2023-11-25 09:20:53

If you messed around with CSS for long enough, chances are you've tried at least once to make a **transition** from `height: 0` to `auto`... only to find out that it **doesn't work!** 😢 

➡️ Luckily, today there is actually a **solution** to this problem: it uses **CSS Grid** under the hood, and it is just **so easy** and it **works flawlessly!**

Let's start with a practical example. I have built this simple **accordion**:

{% codepen https://codepen.io/francescovetere/pen/MWLXjNx %}

The **HTML** for it is pretty straightforward:

```html
<div class="accordion">
  <div class="accordion-title">Hover me!</div>
  <div class="accordion-body">
    <div>
      <p>Lorem ipsum ...</p>
    </div>
  </div>
</div>
```

If you **hover** with your mouse over the accordion, you'll notice that a **dropdown appears**. That's cool, but what if we wanted to make it appear with a nice **smooth transition?**

**I actually tried** to do so in the previous codepen by adding a little transition on the `height` property:

```css
.accordion-body {
  height: 0;
  transition: 500ms height ease;
}

.accordion:hover .accordion-body {
  height: auto;
}
```

❌ Unfortunately, **this doesn't work**: transitioning from `height: 0` to `height: auto`, as I was saying earlier, is something **not possible with CSS.**

🤔 How to solve this? 

Well, a **first solution** could be setting the `height` property to a **fixed number**, instead of `auto`.

This would work, but it's **not such a great approach**: in order to compute this fixed number we would have to resort to **JavaScript**, in order to calculate how much our `.accordion-body` is actually tall... **not really what we aimed for!**

😕 Can we still achieve this effect, but with a **CSS-only** solution?

💡 **Actually, yes!** Why don't we just use `max-height` instead?

```css
.accordion-body {
  max-height: 0;
  transition: 500ms max-height ease;
}

.accordion:hover .accordion-body {
  max-height: 200px;
}

```

This would be the result:

{% codepen https://codepen.io/francescovetere/pen/ExrRNVa %}

Since we are defining a **fixed value** for `max-height`, the browser is now able to **perform the transition correctly**.

😕 The **only problem** is that, since we are defining a fixed value for `max-height`, now the content could **potentially overflow**:

{% codepen https://codepen.io/francescovetere/pen/VwgdmbW %}

If you're sure that your content will always be such that it never reaches a certain height... then it's **perfectly fine to use this method!** Just use an appropriate value for `max-height`, and you're good to go.

**Be aware though**, the **higher the value** for `max-height`, the **weirder the transition gets** (try putting a `max-height: 1000px` in the previous codepen, and see how things change!).

🤔 **Can we do better?** Can we avoid having any fixed `height`/`max-height` in the first place?

🎉 **CSS Grid comes to the rescue!**

✅ We can actually use a **neat trick** which basically consists in making a **CSS grid** with a **single grid item**. 

All we really have to do then, is taking our `grid-template-rows` and make it **transition from `0fr` to `1fr`**: this way, our grid item will transition from 0 to its "natural" height. It's **THAT** simple:

```css
.accordion-body {
  display: grid; 
  grid-template-rows: 0fr;
  transition: 250ms grid-template-rows ease;
}

.accordion:hover .accordion-body {
  grid-template-rows: 1fr;
}

.accordion-body > div {
  overflow: hidden;
}
```

This feels a **lot cleaner.** No fixed heights, no fancy stuff, just our accordion working as expected. **Wonderful!** 😄

{% codepen https://codepen.io/francescovetere/pen/BaGwBRx %}

The **one caveat** to this solution is that you actually need to set an `overflow: hidden` to the `.accordion-body`'s internal `div` in order to make this work. In my opinion, this little extra CSS is totally worth it, but let me know in the comments what you think about it!

🎁 **Bonus tip**

This trick only works because of the **animability** of `grid-template-rows` (and, more generally speaking, of **grid tracks**). 

This is quite a **recent feature** for some browsers: if you visit [this page](https://caniuse.com/mdn-css_properties_grid-template-rows_animation) you'll notice that **grid tracks animability** is something that, for example, only landed in **Chrome** starting from **version 107.** 

At the time I'm writing this article all major browsers supports this feature, but always **check for compatibility** first if you want to use this feature in production code!

<hr>

And that's all! Feel free to leave a comment and let me know if you already knew about this awesome CSS feature! 😉

Till next time! 👋

<a href="https://www.buymeacoffee.com/francescovetere"><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Oibfu3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" loading="lazy" width="434" height="100"></a>