CSS Grid the almighty

CSS Grid is a relatively new spec that saw massive adoption from browser around the start of 2018 and is now used almost everywhere. So what it is about?

Basically, it's about making virtual grids with columns and rows. You might have met 12 column grids in CSS frameworks like Bootstrap before? That's what Grid allows you to replicate in a few lines of code, except it's way more powerful and easy to use.

Even more than Flexbox, it's a massive spec with tons of use cases and syntax tricks. It's extremely powerful but it's also easy to get lost in it, so we'll just try a few layouts and use cases to get you started with columns and rows.

So you like columns?

For this example we'll go with just 6 vertical columns. How would that work?

First we have to use display: grid; on the parent element, just like we did with flexbox. Then we can declare our grid with the grid-template-columns: ???; property.

Hello screen reader users! Several code examples of layouts are demonstrated in this page. There is no real content inside these examples that would help you understand them. So instead, for each code example, I decided tell you the code example is hidden, but you can inspect it with developer tools if you are a one. Sorry for the lack of a better solution.grid-template-columns: repeat(6, 1fr);Hidden code demo below.

So let's break it down, what's going on here? The repeat() shortcut is a function we use to declare the number of columns we wanted instead of writing 1fr 1fr 1fr 1fr 1fr 1fr.

The fr is a CSS unit, like pixels or percentages, that means fractional unit. In this example, 1fr repeated six times means split the space in six and give each children the same space.

So what happens if we decide that the first column should take 2 times the space of other columns? The grid readjust itself nicely:

grid-template-columns: 2fr repeat(5, 1fr);Hidden code demo below.

But wait, what happens if there is not enough children? The grid keeps it's 6 column layouts and populate the 5 elements inside the 5 first columns:

grid-template-columns: repeat(6, 1fr);Hidden code demo below.

If too many children, the grid will create a new row:

grid-template-columns: repeat(6, 1fr);Hidden code demo below.

In Grid tutorials you will often hear about the "explicit" and "implicit" columns and rows. The explicit is the one you declared with your code. The implicit is the one created by the browser when there's no written rules to handle specific use cases or bugs. You can declare rules for both implicit and explicit grids even if I won't go into details on this.

Of course we could have a grid where columns have a fixed size in pixels. Doing so would ensure the columns keep a reasonable size even on mobile, but it would make the whole thing un-responsive!

grid-template-columns: repeat(6, 140px);Hidden code demo below.

At this point, you're probably thinking that a media query is needed to make the grid go from fr units to px units when the viewport is smaller. What a chore right ?...

Well dear reader I have something incredible for you...

(ノ◕ヮ◕)ノ*:・゚✧THE INCREDIBLE
MEGA AWESOME
NO MEDIA QUERIES
RESPONSIVE GRID
〜( ̄▽ ̄〜)
grid-template-columns: repeat(auto-fit, minmax(70px, 1fr));Hidden code demo below.

Try resizing it! Great right?! So what's happening here?

What it means is this: the grid will try to stack as many children as possible inside the available width until the minimum size is met. In this case, a new row will be created.

Ok but how do I position stuff?

In CSS frameworks like Bootstrap, you have utility classes to say start here and span this much columns and you can do exactly the same with CSS Grid, using the grid-column: ? / ?; shortcut property on the column of your choice.

There's actually two syntax you can use:

? / ?
Where the first ? is the starting column and the second ? is the ending column.
? / span ?
Where the first ? is the starting column and the span ? is the width of the column in fr unit.

Let's try different things with our grid:

grid-column: 1 / 3;
grid-column: 5 / span 2;
grid-column: 2 / span 4;
grid-column: 2 / span 1;
grid-column: 5 / span 1;
grid-column: 1 / 7;

Results in:

Hidden code demo below.

Ok, what about the rows?

It's basically the same as the columns, except it's for the rows. Use the grid-template-rows to declare the number of rows you need. And of course, you can decide where to place each children using grid-row, the equivalent for rows of grid-columns. It's super useful for art directed pages as you can place everything where you want.

Hidden code demo below.

All this is quite complicated, is there a simpler way?

It can become messy to work this way, so one final tip for you: the best way to make complex layouts from row and grids is to use grid-template-area: ??; and grid-area: ??;, a very funky yet super useful combination of CSS grid.

With this syntax, you draw your layout inside a string in CSS, declaring names for each of your child elements. Let's say we have 5 elements that we want to shape like a star. The result would look like this:

grid-template-areas:
"lefttop . righttop"
". center . "
"leftbottom . rightbottom";

By doing this, we created a 3 by 3 grid. The . character inside the declaration means an element exists but has no name and thus, should be given empty space. Now all we have to do is report those names to our children and voila:

Hidden code demo below.

This syntax is very useful for more visual minded people and can lead to great art directed pages. The Smashing Magazine website has a very nice article on the subject on this page.

I want MOAR!

If you want to train your CSS grid skills, try playing the amazing Grid Garden game on this page. If you want more examples but in a sort of short video format, visit this page. For a complete free video course on CSS Grid, I recommend this one.

And that's it for modern layout in HTML and CSS!

Congratulations for reading thus far, that was a lot to take! Now let's talk about the content of your pages and about the elements you're going to use to format it!

Next: Order your titles correctly


Initially published: November 23rd, 2020
Generated: March 13th, 2022