I’m pleased to shine a light on the fact that the CSS grid-template-rows
and grid-template-columns
properties are now animatable in all major web browsers! Well, CSS Grid has technically supported animations for a long time, as it’s baked right into the CSS Grid Layout Module Level 1 spec.
But animating these grid properties only recently gained supported by all three major browsers. Shall we take a look at a few examples to get the creative juices flowing?
Example 1: Expanding sidebar
First of all, this is what we’re talking about:
A simple two-column grid. Now, before, you might not have built this using CSS Grid because animations and transitions weren’t supported, but what if you wanted the left column — perhaps a sidebar navigation — to expand on hover? Well, now that’s possible.
I know what you’re thinking: “Animating a CSS property? Easy peasy, I’ve been doing it for years!” Me too. However, I ran into an interesting snag while experimenting with a particular use case.
So, we want to transition the grid itself (specifically grid-template-columns
, which is set on the .grid
class in the example). But the left column (.left
) is the selector that requires the :hover
pseudo-class. While JavaScript can solve this conundrum easily — thanks, but no thanks — we can accomplish it with CSS alone.
Let’s walk through the whole thing, starting with the HTML. Pretty standard stuff really… a grid with two columns.
<div class="grid">
<div class="left"></div>
<div class="right"></div>
</div>
Putting the cosmetic CSS aside, you’ll first need to set display: grid
on the parent container (.grid
).
.grid {
display: grid;
}
Next, we can define and size the two columns using the grid-template-columns
property. We’ll make the left column super narrow, and later increase its width on hover. The right column takes up the rest of the remaining space, thanks to the auto
keyword.
.grid {
display: grid;
grid-template-columns: 48px auto;
}
We know we’re going to animate this thing, so let’s go ahead and throw a transition
in there while we’re at it so the change between states is smooth and noticeable.
.grid {
display: grid;
grid-template-columns: 48px auto;
transition: 300ms; /* Change as needed */
}
That’s it for the .grid
! All that’s left is to apply the hover state. Specifically, we’re going to override the grid-template-columns
property so that the left column takes up a greater amount of space on hover.
This alone isn’t all that interesting, although it’s awesome that animations and transitions are supported now in CSS Grid. What’s more interesting is that we can use the relatively new :has()
pseudo-class to style the parent container (.grid
) while the child (.left
) is hovered.
.grid:has(.left:hover) {
/* Hover styles */
}
In plain English this is saying, “Do something to the .grid
container if it contains an element named .left
inside of it that is in a hover state.” That’s why :has()
is often referred to as a “parent” selector. We can finally select a parent based on the children it contains — no JavaScript required!
So, let’s increase the width of the .left
column to 30%
when it is hovered. The .right
column will continue to take up all the leftover space:
.grid {
display: grid;
transition: 300ms;
grid-template-columns: 48px auto;
}
.grid:has(.left:hover) {
grid-template-columns: 30% auto;
}
We could use CSS variables as well, which may or may not look cleaner depending on your personal preferences (or you might be using CSS variables in your project anyway):
.grid {
display: grid;
transition: 300ms;
grid-template-columns: var(--left, 48px) auto;
}
.grid:has(.left:hover) {
--left: 30%;
}
I love that CSS grids can be animated now, but the fact that we can build this particular example with just nine lines of CSS is even more astounding.
Here’s another example by Olivia Ng — similar concept, but with content (click on the nav icon):
Example 2: Expanding Panels
This example transitions the grid container (the column widths) but also the individual columns (their background colors). It’s ideal for providing more content on hover.
It’s worth remembering that the repeat()
function sometimes produces buggy transitions, which is why I set the width of each column individually (i.e. grid-template-columns: 1fr 1fr 1fr
).
Example 3: Adding Rows and Columns
This example animatedly “adds” a column to the grid. However — you guessed it — this scenario has a pitfall too. The requirement is that the “new” column mustn’t be hidden (i.e. set to display: none
), and CSS Grid must acknowledge its existence while setting its width to 0fr
.
So, for a three-column grid — grid-template-columns: 1fr 1fr 0fr
(yes, the unit must be declared even though the value is 0
!) transitions into grid-template-columns: 1fr 1fr 1fr
correctly, but grid-template-columns: 1fr 1fr
doesn’t. In hindsight, this actually makes perfect sense considering what we know about how transitions work.
Here’s another example by Michelle Barker — same concept, but with an extra column and lot more pizzazz. Make sure to run this one in full-screen mode because it’s actually responsive (no trickery, just good design!).
A few more examples
Because why not?
This “Animated Mondrian” is the original proof of concept for animated CSS grids by Chrome DevRel. The grid-row
‘s and grid-column
‘s utilize the span
keyword to create the layout you see before you, and then the grid-template-row
’s and grid-template-column
‘s are animated using a CSS animation. It’s nowhere near as complex as it looks!
Same concept, but with more of that Michelle Barker pizzazz. Could make a nice loading spinner?
Wrapping up with a bit of nostalgia (showing my age here), the not-very-griddy animated CSS grid by Andrew Harvard. Again — same concept — it’s just that you can’t see the other grid items. But don’t worry, they’re there.
Browsers still don’t support animating grid-template-rows in a way that will actually change the size of the grid itself, sadly. Within the grid stuff will get animated but if you have a grid, and content below it, then animate its grid-template-rows to be, say, smaller, the content below will not smoothly animate to change its position based on the new grid height.
❤❤❤
Great article and love the idea for using grid animations for navigation.
This is great! Thanks for sharing
It does not seem to work in Firefox
awesome gird animated, really the interested article. in the future it must needed, thank you.
It does, except the examples using :has() which firefox do not support yet.
I think that’s because most of the examples make use of the :has() selector, which is not yet supported in Firefox.
I’m using the latest Firefox Developer Edition and it works
Same here. But what i found out is that the :has() selector can be turned on from about:config of fireofx. Even then the :has(.left:hover) doesn’t work but :has(.left) works.
I really wanted to use that :(
Wow this is amazing. The menu animation and the muffins cookies animation was best among these. The best part is the codepen.
Michelle Barker’s design doesn’t work for me (latest FF on Win11 for Workstations). The lower row is OK, on the upper row the texts are just shaking, I don’t get a photos.
Now this is really very nice and a welcome to Grid.
Thank you so much for sharing
Right now I am only using a drag and drop website Strikingly. It works for me, but I know this is what all the bigger more powerful websites are doing. CSS coding with unlimited color graphics and templates. I hope to be able to correspond with you all on this, but for now I stand impressed for sure.
Great article! I’m looking forward to trying this out. Just wondering how performant it is to animate grid properties? Thinking about the recomendations to not animate properties that trigger layout or paint.
No issues so far. If I had to guess, it would be the most performant way of going about the concept/effect.
Firefox 109, works.
Note: If grid columns are set to min-content, animation doesn’t work.