This tutorial will dive deep into the CSS Grid Layout exploring almost all properties and features. In the end, you will be fully equipped to tackle any layout with this great CSS addition.
A grid is a two-dimensional grid system. It can be used to build complex layouts as well as small user interfaces.
To make an element a grid, set its display property to grid.
.grid-to-be {
display: grid;
}
Doing this makes .grid-to-be
a grid container and its children grid items.
Grid Tracks are the spaces between two Grid Lines. The rows and columns in a Grid are Grid Tracks.
We can create columns by using the grid-template-columns
property. To define columns set this grid-template-columns
property to column sizes in the order that you want them in the grid to appear. Let’s have a look:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
}
This defines three 100px width columns. All grid items will be arranged, in order, in these columns. The row height will be equal to the height of the tallest element in that row, but this can be changed with grid-template-rows
.
Note that, with only columns and no rows defined, elements fill columns and then flow back in rows. This is because of the implicit grid that Grid has created with grid lines and grid tracks.
grid-template-rows
is used to define the number and size of rows in a grid. It is similar in syntax to grid-template-rows
.
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
Only having the grid-template-rows
property on without grid-template-columns will result in the column width being equal to the width of the widest element in that row.
grid
is shorthand for three properties: grid-template-rows, grid-template-columns
, and grid-template-areas
.
The way you use it is like this:
.grid {
grid-template:
"header header header" 80px
"nav article article" 600px
/ 100px 1fr;
}
You define the template areas like you normally would, place the width of each row on its side and then finally place all the column widths after a forward slash. Like before, you can place all of it on a single line.
The fr
unit is a new unit created for CSS Grid Layout. The fr
unit helps to create flexible grids without needing to calculate percentages. 1fr
represents one fraction of the available space. The available space is divided into the total number of fractions defined. So, 3fr 4fr 3fr
divides the space into 3+4+3=10 parts and allocates 3, 4, and 3 parts of the available space for the three rows/columns respectively. For example:
.grid {
display: grid;
grid-template-columns: 3fr 4fr 3fr;
}
If you mix fixed units with flexible units, the available space for the fractions is calculated after subtracting the fixed space. Let’s look at another example:
.grid {
display: grid;
grid-template-columns: 3fr 200px 3fr;
}
The width of a single fraction is calculated like this: (width of .grid
- 200px) / (3 + 3). The space of the gutters, if any present, would have also been subtracted initially from the width of .grid
. This is the difference between fr
s and %
s that percentages don’t include the gutter that you define with grid-gap
.
Here 3fr 200px 3fr is essentially equal to 1fr 200px 1fr.
The explicit grid is the one created with properties grid-template-rows
and/or grid-template-
columns. The implicit grid consists of the grid lines and grid tracks that Grid creates to hold items outside of the manually created grid with the grid-template-*
properties.
When we create a grid like this:
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
Even though we have only defined the columns, individual cells that are direct children of .grid
lay themselves out in rows. This is because of the rules of auto-placement that are part of Grid.
To define the size of the created columns, implicitly-created grid column tracks, which were not defined by grid-template-columns
, use the grid-auto-columns
property. The default value is auto; you can set it to any value you want.
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-auto-columns: 50px;
}
grid-auto-rows
works similar to grid-auto-columns
. To define the size of the created rows, implicitly-created grid row tracks, which were not defined by grid-template-rows, use the grid-auto-rows
property. The default value is auto
; you can set it to any value you want.
.grid {
display: grid;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 50px;
}
The grid-auto-flow
property controls how grid cells get flowed into the grid: in rows or columns. The default value is row
.
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-auto-flow: column;
}
The grid
cells in the above grid fill columns one by one until no items are left.
Placing items in a grid using line numbers is called line-based placement.
If you want a specific grid item to start on a particular row line then you can have something like this:
.grid-item {
grid-row-start: 3;
}
If you want a specific grid item to end on a particular row line then you can have something like this:
.grid-item {
grid-row-end: 6;
}
If you want a specific grid item to start on a particular column line then you can have something like this:
.grid-item {
grid-column-start: 3;
}
If you want a specific grid item to end on a particular column line then you can have something like this:
.grid-item {
grid-column-end: 6;
}
You may use the grid-row
and grid-column
properties to manually place and size grid items. Each property is the shorthand for their respective star and end properties: grid-row-start
, grid-row-end
, grid-column-start
, and grid-column-end
.
Us a forward slash ”/” to separate the start and end values:
.grid-item {
grid-column: 3 / 5;
grid-row: 2 / 7;
}
You can use grid-area as a shorthand for both grid-row and grid-column. It works like this: / / / :
.grid-item {
grid-area: 2 / 3 / 7 / 5;
}
This code behaves the same as the code in the previous heading.
To span an element across the grid, you can use the grid-row
or grid-column
property. Set the starting line 1 and the ending line -1. Here 1 means the leftmost grid line and -1 means the rightmost grid line in the relevant axis. This would be opposite, in a right to left writing script, that is 1 meaning the rightmost line and -1 meaning the leftmost line.
.grid-item-weird {
grid-column: 1 / -1;
}
If you want a single item to take up the entire grid, you can do this to both grid-row
and grid-column
:
.grid-item-weird {
grid-row: 1 / -1;
grid-column: 1 / -1;
}
Or simply:
.grid-item-weird {
grid-area: 1 / 1 / -1 / -1;
}
Instead of explicitly defining the line numbers when using grid-row
and grid-column
, you may use the span
keyword to state how many rows or columns the item should cover:
.grid-item {
grid-column: 3 / span 2;
}
You may also tack the item onto the ending line and span it across in the other direction. The code below achieves the same result as above:
.grid-item {
grid-column: span 2 / 5;
}
You may use span
for rows the same way.
Grid Cell is the space between four intersecting Grid Lines just like a table cell.
Grid Areas are grid cell(s) taking up a rectangular area on the grid. They are created using named grid areas or line-based placement.
Instead of placing and sizing individual grid items with things like span
, grid-column
, etc, you may use what’s called Template Areas. The grid-template-areas
allows you to name areas of a grid so that they may further be filled up by grid items.
.grid {
display: grid;
grid-template-columns: 100px 1fr 100px;
grid-template-rows: 100px 800px 100px;
grid-template-areas:
"header header header"
"sidebar-1 content sidebar-2"
"footer footer footer"
}
Here a single pair of quotes represents a row of the grid. You could have it all in a single line and not align the columns, but I have done just so that it looks cleaner. So, first I have defined three columns and three rows and then named each cell. By having “header” repeated three times in the first row, what I’m telling CSS to do is to cover that whole thing with the grid item named header. The rest is likewise.
Here’s how you name each grid item to have the space that was defined for it using grid-template-areas
:
.header {
grid-area: header
}
.sidebar-1 {
grid-area: sidebar-1
}
.content {
grid-area: content
}
.sidebar-2 {
grid-area: sidebar-2
}
.footer {
grid-area: footer
}
Nothing could ever be easier than that, especially other CSS methods for laying out content.
Previously, you have seen that grid-area
is used for line-based positioning too.
You may use a dot if you want to leave a cell empty:
.grid {
display: grid;
grid-template-columns: 100px 1fr 100px;
grid-template-rows: 100px 800px 100px;
grid-template-areas:
"header header header"
"sidebar content sidebar"
"footer footer ."
}
Here the footer ends with the second column.
grid
is shorthand for three properties: grid-template-rows
, grid-template-columns
, and grid-template-areas
.
The way you use this is like this:
.grid {
grid-template:
"header header header" 80px
"nav article article" 200px
/ 100px auto;
}
You define the template areas like you normally would, place the width of each row on its side and then finally place all the column widths after a forward slash. Like before, you can place all of it on a single line.
The repeat()
function helps to make grid tracks listings a little non-redundant and adds a bit of semantic layer to them. It is quite easy and intuitive to use. Let’s have a look:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr); // this is the same as 1fr 1fr 1fr
}
You may repeat a certain pattern of track listing, as well, like this:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr 2fr); // this is the same as: 1fr 2fr 1fr 2fr 1fr 2fr
}
The repeat() doesn’t need to be the only part of the value. You may add other values before and after it. For example: grid-template-columns: 2fr repeat(5, 1fr) 4fr;.
grid
is shorthand for six properties: grid-template-rows
, grid-template-columns
, grid-template-areas
, grid-auto-rows
, grid-auto-columns
, and grid-auto-flow
.
First of all, you may use like grid-template
like this (the previous example):
.grid {
grid:
"header header header" 80px
"nav article article" 200px
/ 100px auto;
}
Second of all, it is not what it looks like: That is, grid is not like the property css:
Yes, you read that right: a property called css. The Shorthand for all CSS properties. I came across it in a revelatory experience during transcendental meditation involving CSS and whatnot. But I won’t teach you how to use it. I’m keeping it for a future tutorial. Till then keep moving high on the ladder to CSS enlightenment.
Third of all, you use grid
a certain way. You can combine grid-template-rows
with grid-auto-columns
or you can combine grid-auto-rows
with grid-template-columns
. The syntax of these are pretty simple:
.grid-item {
/_ grid: <grid-template-rows> / <grid-auto-columns>; _/
/_ grid: <grid-auto-rows> / <grid-template-columns>; _/
}
For example:
.grid-item-1 {
grid: 50px 200px 200px/ auto-flow 60px;
}
.grid-item-2 {
grid: auto-flow 50px / repeat(5, 1fr);
}
Note that you actually use the keyword auto-flow before the value.
Gutter is the space that separates grid rows and grid columns individually. grid-column-gap
, grid-row-gap
, and grid-gap
are the properties used to define gutters.
grid-row-gap
is used to define the space between individual grid rows. It works like this:
.grid {
display: grid;
grid-template-rows: 100px 100px 100px;
grid-row-gap: 10px;
}
This spaces out the grid rows 10 pixels apart from each other.
grid-column-gap
is used to define the space between individual grid columns. It works like this:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-column-gap: 10px;
}
This spaces out the grid columns 10 pixels apart from each other.
grid-gap
is the shorthand property that combines grid-column-gap
and grid-row-gap
. One value defines both gutters. For example:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-gap: 10px;
}
We can control the order of grid cells using the order
property. Let’s look at the following example:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-gap: 10px;
}
.grid .grid-cell:nth-child(5) {
order: 1;
}
Above, the fifth grid cell is placed last in the grid because the other grid cells have no order defined at all. If defined, then the numerical order would be followed. Two or more grid cells can have the same order. The ones with the same order or no order at all are placed according to the logical order of the HTML document. Let’s have a look here:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-gap: 10px;
}
.grid .grid-cell {
order: 1
}
.grid .grid-cell:nth-child(5) {
order: 2;
}
The above example produces identical results to the previous example.
The minmax()
function is new to CSS Grid Layout. This function gives us a way to specify the minimum as well as the maximum size for grid tracks.
Let’s have a look at the following example:
.grid {
display: grid;
grid-template-columns: 1fr minmax(50px, 100px) 1fr;
}
With the above code in effect, on reducing the window width, the middle column retains its 100px width until the first and last columns are reduced to the width of their content. This is especially useful for making responsive layouts.
If the parent container’s dimension is fixed, like a fixed width, the auto keyword as the width of a grid item will make the item fill the whole width of the container. In the case of multiple items, the space is divided just like fr
s. But if auto
is used with fr
, auto
behaves as the width of the content of that item and the rest of free space is divided to make up fr
s.
The fitcontent()
function is used when you want the width/height to behave like auto
but also have a maximum width/height in case you don’t want it to get all the way that big.
.grid-item {
width: fitcontent(200px);
}
Here it will, on the minimum side fit the content and on the maximum be as big as 200px.
You can use the auto-fill
to fill the relevant axis (row or column) with the most number of grid tracks without overflowing. The way you achieve this is using the repeat()
function:
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 50px);
}
But this would reduce the flexibility of individual tracks. You can have both auto-fill functionality and flexibility by using minmax()
with it.
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(50px, 1fr));
}
This way, you can have at least one column and at most all columns of 50px in a particular browser width.
Note that auto-fill* creates grid tracks even though they may not be filled with cells.
auto-fit
behaves the same as auto-fill
except that it collapses all empty repeated tracks. An empty track is one with no grid items placed in it or spanning across it.
With the help of the dense
keyword, you can backfill items into empty grid cells which were created because of weird things you were trying to do like spanning and whatnot. Any span, you may use the dense
keyword with grid-auto-flow
like this:
.grid {
display: grid;
grid-template-column: repeat(auto-fill, minmax(50px, 1fr));
grid-auto-flow: dense;
}
You can use this with an image gallery but be careful with something like a form. You mostly want the form sub-elements in a specific order.
At the time of this writing, there is good browser support for CSS Grid Layout. According to caniuse.com, all major browsers support CSS Grid Layout except Internet Explorer 11 which has partial support with -ms- prefix and Opera Mini having no support at all.
CSS Grid allows us to make layouts with more control, ease and speed than previous method systems. In this tutorial, we learned all major elements of Grid which includes creating tracks, positioning and sizing cells, and making the grid fluid and responsive with keywords like auto-fill
and functions like minmax()
.