Grid Guide

Learn the Basics of the Grid Layout

What is Grid and Why Should I Care?

Let's start with the why: imagine that you want to build a site. You have some content to place and you would like it to look nice and easily readable from every device.

At this point you have one main question that you should ask yourself: do you have a specific idea of how this content should be arranged?

If the answer is yes then Grid is perfect for you.

Otherwise, if you don't care how the content is arranged and you would just rather have the browser place the elements automatically along one direction, then take a look at the Flexbox Guide.

What is Grid? Fundamentally it's exactly what the name suggests: a table.

Grid is a CSS layout that allows you to divide the page into several rows and columns that you specify. This creates several squares called "cells".
You will then be able to place the content you want in these cells, and you will also be able to span the content over multiple cells.
Grid is smart too: it will add more cells if the content needs them and it can arrange itself to respond to different screen sizes.

Grid works very well to build the foundation of your page, and to place the various elements in the desired locations.
It can also be used together with other techniques, like Flexbox, to get the best of both worlds.

Since you are still reading, let's assume that you want to make a site and that you already know where you would like to place the element in it. Grid sounds like a good choice for this task. Now what?


The essentials of building a Grid

We first need a container (like a div element) that we can turn into a Grid.
This can be done simply by adding a class to this element. Let's first create the class to apply to the container then:

.gridContainer { display: grid; }
Hello
there
fellow
Box

Now every element that receives the "gridContainer" class we have just created will technically be a grid! But that by itself doesn't do anything. To actually do something with Grid we need to specify how we want to divide it in rows and columns.
We also need some elements inside to arrange, or there would be nothing to see!

Let us create a grid of 2 rows and 2 columns.

Hello
there again
fellow
Box
.fourFour {
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr 1fr;}
<div class="gridContainer fourFour">
<div class="boxA">Hello</div>
<div class="boxB">there again</div>
<div class="boxC">fellow</div>
<div class="boxD">Box</div>
</div>

This is already a basic and functioning grid. There are of course many other settings that we will explore now.

Now introducing a new unit: fr

Grid brings to the table also a unique new unit that can be used with it: "fr".
It stands for "fraction" but it can be easier to imagine as "free space".
Basically the fr unit is a flexible and smart unit that will take as much free space as it's left in the grid. In the example above the 4 boxes automatically divided the available space equally among themselves.

It's also easy to combine it with other units like "px" to create mixed grids with cells that are fixed by using pixels and then allocating the remaining space proportionally with fr.
Row 1, Column 1
Row 1, Column 2
Row 2, Column 1
Row 2, Column 2
.frExample{
grid-template-rows: 1fr 3fr;
grid-template-columns: 500px 1fr;}

The first column is fixed at 500px, while the second one will use the remaining space.
The rows instead are both filling the free space, but they will occupy different amounts of it. The second row will take 3 times as much free space as the first row.

If you would rather create both rows and columns with one command, it's actually possible: just use the "grid-template" command instead.

Row 1, Column 1
Row 1, Column 2
Row 2, Column 1
Row 2, Column 2
grid-template: 1fr 3fr / 500px 1fr;

It works exactly the same as using those commands separately. The first values refer to the grid-template-rows and then separated by a "/" we can find the grid-template-columns values.

Choosing a minimum and maximum dimension

An interesting extra command available when creating a grid is "minmax".
As the name suggests it allows you to specify the smallest and biggest size a specific row or column can have, giving a specific amount of responsiveness to the grid.

grid-template: 200px 200px / minmax(50px, 150px) 150px 300px;
Row 1, Column 1
Row 1, Column 2
Row 1, Column 3
Row 2, Column 1
Row 2, Column 2
Row 2, Column 3

In this example the first column can be a minimum of 50px and stretch to a max of 150px, if the space allows it.

Bonus: What happens if I have too many items?

We have created a grid and we have noticed it is composed of rows and columns, each having a certain number of lines which form cells. Every cell will contain an element. What happens if we have more elements than cells?
Grid is quite smart: if it has to place more items than they would fit in the current specified grid, the grid will grow in size automatically. This creates some "implicit lines", which try to follow the directions of the specified grid while still welcoming the new items.

80px
130px
80px
130px
grid-template-columns: 80px 130px;

This can be seen in the example above: even though only two column lines were specified, since the grid had four elements to fit it automatically created another row to fit them.

Creating multiple lines with one command

It would be nice to create a grid without having to input every row and column individually though. Luckily there is a command for that: repeat.

If you want to create a grid like this for example:

grid-template-columns: 20px 20px 20px;

You could just write it using repeat instead for the exact same result:

grid-template-columns: repeat(3, 20px);

The first number is specifying how many lines it has to create. The second number is the dimension of those lines.

It is even possible to create lines following a certain pattern. Let's see it in an example.

grid-template-columns:
repeat(3, 80px 130px);
80px
130px
80px
130px
80px
130px

Here the repeat function is repeating a specified pair of a 80px followed by a 130px cell, three times.

Changing the space between cells

So we have learned how to create different cells and choose the size of our grid. It's also possible to modify the space between cells with a simple command "grid-gap". Let's see it in an example, using the same grid as above but choosing a custom gap value.

Row 1, Column 1
Row 1, Column 2
Row 2, Column 1
Row 2, Column 2
grid-gap: 20px 50px;

By adding just one line, the cells have now the spaces we want!
The first value refers to the space between rows, while the second one specifies the spaces between columns. We can also use only one value (like 50px) to set both rows and column gaps to the same distance.

Recap: building a simple grid

Let's see with one example a very simple grid built using everything shown in this section.

.recapGrid1{
display:grid;
grid-template:
200px repeat(2, 1fr 2fr) / 20% 40% 100px;
grid-gap: 10px;
}
Row 1, Column 1
Row 1, Column 2
Row 1, Column 3
Row 2, Column 1
Row 2, Column 2
Row 2, Column 3
Row 3, Column 1
Row 3, Column 2
Row 3, Column 3
Row 4, Column 1
Row 4, Column 2
Row 4, Column 3
Row 5, Column 1
Row 5, Column 2
Row 5, Column 3

There you have it: a simple and complete 3x5 Grid, with custom cell size and gap size.


Place and move elements in the Grid

Just as important as creating a grid is the control of where the items should be placed inside the created grid. Let's look at it here.

Row 1, Column 1🍕
Row 1, Column 2🥑
Row 1, Column 3🐉
Row 2, Column 1🚚
Row 2, Column 2🐟
Row 2, Column 3🍂
Row 3, Column 1🦑
Row 3, Column 2🦊
Row 3, Column 3🐑

Here we can see many elements spanning multiple lines. By using "grid-row" and "grid-column" it was possible to individually place an element in a desired position.

<div class="gridContainer">

<div class="boxA" style="grid-column: 1 / 3;">Row 1, Column 1🍕</div>

<div class="boxB" style="grid-row: span 2;">Row 1, Column 2🥑</div>

<div class="boxC" style="grid-row: 2 / -1;" >Row 1, Column 3🐉</div>

<div class="boxC">Row 2, Column 1🚚</div>

<div class="boxB" style="grid-column: span 3;">Row 3, Column 1🦑</div>

<div class="boxA" style="grid-column: auto/4;">Row 3, Column 3🐑</div>

</div>

Let's look at the "pizza" element for example. We are adding a css line to that element that specifies where it should be placed along the grid columns. Writing "grid-column: 1/3" means that the element will start on column line one and stretch until column line 3.

This was done a bit differently for item "avocado" where we have simply told the element to stretch across two rows or "span 2".

It's interesting to look also at the "dragon" element. The element will start at row 2 and then will end at "-1". What?
That is actually a small trick to ask an element to stretch until the end of the grid. In this case it only stretched to the end of the 3x3 grid that was specified directly, but it does not stretch over the implicit lines created automatically by grid.

The "sheep" element is instead starting at the value of "auto" and ending at column line 4. This will give the item an automatic span of 1.

Align Elements in the Grid

Now that we now how to create grids and place elements in the grid, we might want to have more control on how these elements are spaced and look like: you need to control their alignment.

The quickest way to choose how a specific element will align its own content in the grid is using the "place-self" command.

It is actually a shorthand for two other commands called "align-self" and "justify-self" in one, so let's see this shortcut in action.

.item-a {
place-self: center stretch; }

The command "place-self" takes two values: the first one (align-self) will choose how the item will align vertically, along the column. The second value (justify-self) will choose how to justify the item along the row.

There are 5 commands that you can choose both for aligning items vertically or horizontally:

auto
auto
auto
auto
auto
align-self: auto
start
end
center
stretch
justify-self: auto
start
end
center
stretch
place-self: auto
start
end
center
stretch
place-self: auto center
start end
end stretch
center end
stretch start

On the first row we can see how the grid would look like without any alignment.
On the second row we find the 5 possible values applied to align-self. Worth noticing how while both auto and stretch look the same, the difference is that while stretch is independent, auto will copy its parent element. So typically if an alignment for the whole grid has been specified, auto will copy it for the element itself (it's the default behaviour without any custom alignment).
Third row contains all 5 examples of justify-self.
The fourth row displays both align and justify being modified at once with the place-self shortcut. In this case by choosing only one value on place itself we are setting both align and justify to the same value, but they can be chosen differently, like shown in the fifth row.


What more can you do with a Grid Container?

Customize the alignment of the Grid itself

We have seen how to select different alignments for the elements in a grid, but even the grid itself can be changed in many ways. In many ways this is a bit like setting the whole grid to behave in a certain way instead of a single element. You can always customize a single element to behave differently though, like shown above.

Let's look at the shorthand to set up both the vertical alignment and horizontal justifying in one command here too: "place-items". It takes the exact same values shown above for place-self, minus "auto" which is not used here.
Let's see some small grids showing the various possibilities.

place-items

Default
Default
Default
Default
stretch
stretch
stretch
stretch
start
start
start
start
end
end
end
end
center
center
center
center
end start
end start
end start
end start
.gridContainer{
place-items: end start; }

These are basically the exact same customization available with place-self, but applied to the whole grid with just one command.

place-content

There is another shorthand to customize the placing of a whole grid though:
"place-content".

If the previous command was useful to align every item inside a grid, "place-content" instead allows you to move the entire grid and to align on the page. In addition to the four commands seen above, place-content supports even three more.
Just like in the previous examples, writing only one value will apply it to both alignment and justify, but they can be specified separately. Let's see.

Default
Default
Default
Default
stretch
stretch
stretch
stretch
start
start
start
start
end
end
end
end
center
center
center
center
space-around
space-around
space-around
space-around
space-between
space-between
space-between
space-between
space-evenly
space-evenly
space-evenly
space-evenly
center space-evenly
center space-evenly
center space-evenly
center space-evenly
end start
end start
end start
end start
.gridContainer{
place-content: center space-evenly; }

Renaming lines and areas

An interesting function of grid is the ability to give your own name to lines, instead of referring to to cells as "Row 1, Column 1" as we did above.

.frExample{

grid-template-columns: [column-1] 500px [column-2] 1fr;

grid-template-rows: [row-1] 1fr [row-2] 3fr; }

By choosing a name and writing it before the dimension, surrounded by [ ], you can now refer to that specific line with the name you've chosen. You could even give more than one name to a line like this "[column-start column-end] 500px".

This even works with the repeat function, which can automatically name things (with the same name though).

.gridContainer {
grid-template-rows: repeat(4, 20px [col-start]); }

Dividing the Grid in areas

An alternative way to place items around the grid is by first assigning a name to one or more cells, and then assign the element we want to that area. Let's see how to create an area first.

.gridAreas {

grid-template: 1fr 2fr 1fr / 1fr 2fr 1fr;

grid-template-areas:
"side header header" ". main main" "footer footer footer"; }

Here we first defined a simple 3x2 grid structure with "grid-template". Then we assigned to each of those cells a name.

Header
Footer
Side
Main
<div class="gridAreas">

<div class="boxA" style="grid-area: header;">Header</div>

<div class="boxC" style="grid-area: footer;">Footer</div>

<div class="boxB" style="grid-area: side;">Side</div>

<div class="boxD" style="grid-area: main;">Main</div>


</div>

By assigning to an element the desired grid area the element will then occupy the desired cells. A period "." can be used to leave a cell empty, although they shouldn't be used to separate two instances of the same area.

Controlling Grid implicit lines

As mentioned above, when there are more elements in a grid than the grid is able to place around, it will automatically extend itself to fit them in.
There is actually some degree of control on how these extra lines are created by using "grid-auto-columns" and "grid-auto-rows". Let's see by creating a 2x2 grid with 100px wide cells, but inserting an extra element.

grid-template: 100px 100px / 100px 100px;
grid-auto-columns: 50px;
grid-auto-rows: 150px;
Actual Grid
Actual Grid
Actual Grid
Actual Grid
Auto Grid

We have specified that every auto element should be created as a column of 50px and row of 150px. But the column size is still clearly 100px, so what's happening?
What's happening is that Grid is currently set to create auto elements as rows (the default behaviour)! We can actually change that though, with "grid-auto-flow".

Let's see the same example, but this time we will specify that new elements should be placed in columns.

Actual Grid
Actual Grid
Actual Grid
Actual Grid
Auto Grid
grid-auto-flow: column;

Other than "row" and "column" there is also a third value called "dense" that is supported by grid-auto-flow. It basically asks the grid to try to fill any empty space as soon as possible, by using elements that could fit in the space.


Finally: Play with Grid

Of course there is no better way to understand these concepts than to try them out when you need them, but until then there is a simple way to get some practice: play a game!

Grid Garden is a great browser game that let's you use grid practically to solve some puzzles.

Griddy.io is a great place to try out simple grid design in a sandbox.

Now go and improve your sites by using Grid!