1. Web Design
  2. HTML/CSS
  3. CSS

Introduction to the CSS Grid Layout With Examples

Scroll to top
Final product imageFinal product imageFinal product image
What You'll Be Creating

In this tutorial, I will cover the basics of the CSS grid layout with example scenarios. CSS Grid is supported by almost all modern browsers now, and it is ready to be used in production. Unlike other layout methods such as flexbox, the grid layout gives you two degrees of freedom, which makes it so versatile that positioning the elements is just a breeze.

I'll also touch on the new CSS subgrid feature, which allows grid children to easily inherit the grid row and column configurations from the parent grid.

HTML Structure for the CSS Grid Layout

In order to use the CSS Grid layout, your HTML elements should have a specific structure.

You need to wrap the elements that you want to control within a parent container DIV.

1
<div class="wrapper">
2
  <div class="div1">1</div>
3
  <div class="div2">2</div>
4
  <div class="div3">3</div>
5
  <div class="div4">4</div>
6
</div>

Let's add some styling for our DIVs so that we can distinguish them easily.

Also, set the display: grid in your wrapper DIV so that we can start using the grid layout.

1
.wrapper > div{
2
  background-color: orange;
3
  border: 1px black solid;
4
}
5
6
.wrapper > div:nth-child(odd){
7
  background-color: indianred;
8
}
9
10
.wrapper{
11
  display: grid
12
}

From this point on, all the styling will go into the wrapper DIV. If we ever want to control the child DIVs at any point, then we will be adding grid-specific styling rules for the specific child DIV.

Rules on Parent DIV

The first things we need to learn about the grid layout are grid-template-columns and grid-template-rows. Those two rules basically control how your grid is shaped.

The value of these rules can be a length, a percentage, or a fraction of the free space in the grid. You can also set any value to auto, which fills up the remaining space.

Let's see some examples below.

grid-template-columns and grid-template-rows

grid-template-columns

1
.wrapper{
2
  display: grid;
3
  grid-template-columns: 100px 100px 100px
4
}

1
.wrapper{
2
  display: grid;
3
  grid-template-columns: 100px auto 100px
4
}

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: 1fr 1fr 1fr 1fr;
4
}

grid-template-columns and grid-template-rows

Let's start building a real grid, in which we have control over both columns and rows.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: 1fr 1fr;
4
  grid-template-rows: 50px 50px;
5
}

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: 100px 20px 250px;
4
  grid-template-rows: 150px 40px;
5
}

Here I just added two more child DIVs to the HTML for the same CSS.

Repeat a grid-template Pattern

If you have a repeating pattern for grid-template, you can just use repeat and tell it how many times to repeat the same pattern.

For instance, say you have 12 elements, and you want to lay them out horizontally with equal width. You could repeat 1fr 12 times inside grid-template-columns, which is not effective. So, instead, you can use repeat(12, 1fr).

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(12, 1fr)
4
}

Likewise, you can repeat a pattern.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(4, 1fr 5fr 10fr);
4
}

grid-auto-columns and grid-auto-rows

This rule helps you to set the width and height of grid cells.

If you don't set this rule, your grid rows and columns will expand with the content.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(4, 1fr);
4
  grid-auto-rows: 100px;
5
}

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(4, 1fr);
4
  grid-auto-rows: 20px 80px;
5
 }

One nice feature to use with grid-auto rule is the minmax function.

You simply set the minimum size as the first parameter and the maximum as the second parameter. If you set auto for the second parameter, you get a responsive cell size.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(4, 1fr);
4
  grid-auto-rows: minmax(50px, auto)
5
 }

Below you see two different DIV contents with the same CSS rules.

Grid-gap

As the name implies, this rule creates a gap between grid cells.

If you use grid-gap: 5px, you get a 5px gap between each cell. Alternatively, you can only set the row or column gaps, with grid-row-gap: 5px and grid-column-gap: 5px respectively.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(4, 1fr);
4
  grid-auto-rows: minmax(50px, auto);
5
  grid-gap: 5px;
6
 }

Rules on Child Divs

So far, we've only focused on the shape of the grid and items just flowed in the grid. Now we will learn how to control each item individually.

In order to position the items, we use grid lines as a reference. Below you see the row and column lines in black and orange respectively for a 2x4 grid.

We will use the grid-column and grid-row rules with line numbers to position the elements.

For example, if we set grid-column: 1/3 for the first child div, it will use the first two cells in the grid.

Consider the HTML and CSS below:

1
<div class="wrapper">
2
  <div class="div1">1</div>
3
  <div class="div2">2</div>
4
  <div class="div3">3</div>
5
  <div class="div4">4</div>
6
  <div class="div5">5</div>
7
  <div class="div6">6</div>
8
  <div class="div7">7</div>
9
  <div class="div8">8</div>
10
</div>
1
.wrapper {
2
  display: grid;
3
  grid-template-columns: repeat(4, 1fr);
4
  grid-auto-rows: 100px;
5
  grid-gap: 5px;
6
 }

We have four equally sized columns and eight elements in the wrapper DIV.

1
 .div1{
2
   grid-column: 1/3;
3
 }
4
 

1
 .div1{
2
   grid-column: 1/3;
3
   grid-row: 1/3;
4
 }

You can also combine these two rules into a single rule, grid-area: rowStart/columnStart/rowEnd/columnEnd.

1
 .div1{
2
   grid-area: 2/2/3/4;
3
 }

As illustrated in the above example, elements are not bound to the HTML structure. Notice how the first element is repositioned with the grid-area rule.

grid-area and grid-template-areas

You can name each child element and use these names to create your grid. This is really powerful, and it makes doing layout more intuitive.

So we define a DIV for each element we are planning to place in our grid system.

I am planning to have a header, leftColumn, rightColumn, middleTop, middleBottom, and a footer.

So in my HTML I need that many child DIVs. The class names can be anything.

1
<div class="wrapper">
2
  <div class="header">Header</div>
3
  <div class="leftCol">LeftCol</div>
4
  <div class="rightCol">RightCol</div>
5
  <div class="midTop">midTop</div>
6
  <div class="midBottom">midBottom</div>
7
  <div class="footer">Footer</div>
8
</div>
9

Then, inside my CSS, I set the grid-area names. Those names can be anything; they are not supposed to match the class names.

1
.header{
2
   grid-area: header;
3
   background-color: LightSeaGreen ;
4
 }
5
 
6
 .leftCol{
7
   grid-area: leftCol;
8
   background-color: orange;
9
 }
10
 
11
 .rightCol{
12
   grid-area: rightCol;
13
   background-color: lightblue;
14
 }
15
 
16
  .midTop{
17
   grid-area: midTop;
18
   background-color: lightgrey;
19
 }
20
 
21
 .midBottom{
22
   grid-area: midBottom;
23
   background-color: pink;
24
 }
25
 
26
 .footer{
27
   grid-area: footer;
28
   background-color: lightgreen;
29
 }

Then, inside my wrapper DIV, I use the grid-template-areas rule to lay out those elements by referring to their defined names.

Notice that I have a 4x4 grid.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: 1fr 4fr 4fr 1fr;
4
  grid-template-rows: 50px 100px 100px 30px;
5
  grid-template-areas:
6
  "header header header header"
7
  "leftCol midTop midTop rightCol"
8
  "leftCol midBottom midBottom rightCol"
9
  "footer footer footer footer";
10
  grid-gap: 5px;
11
 }

If, for example, I want the footer to take only two columns and be centered, then I simply replace the first and the last appearance of footer with a dot (.) in grid-template-areas.

1
.wrapper {
2
  display: grid;
3
  grid-template-columns: 1fr 4fr 4fr 1fr;
4
  grid-template-rows: 50px 100px 100px 30px;
5
  grid-template-areas:
6
  "header header header header"
7
  "leftCol midTop midTop rightCol"
8
  "leftCol midBottom midBottom rightCol"
9
  ". footer footer .";
10
  grid-gap: 5px;
11
 }

Introducing CSS Subgrids

Before we dive deep into the new CSS subgrid feature, let's first take a look at a problem typically encountered with regular grids.

We'll take a look at an example by Kevin Powell which uses normal grid alignment. In his demo example, six cards are aligned into rows in a container .card-grid element using the display:grid CSS property.

1
<div class="card-grid">
2
  <div class="card">
3
    // Content and image
4
  </div>
5
   <-- 5 more cards -->
6
</div>
Screenshot of gridScreenshot of gridScreenshot of grid
Screenshot of grid

Each card is composed of an image, a title, and a description, and although each of them has a different title, the overall layout looks quite neat. But what happens when we resize the window and make it smaller? Take a look at the result below.

Misalignment of gridsMisalignment of gridsMisalignment of grids
Misalignment of grids

They do not share a consistent layout because the content inside each of them is different. The space allocated for the image in each card depends solely on its corresponding content's size. Hence images that exist in cards with longer text are smaller than those existing with smaller text. This creates an incongruous layout, which leads to a very messy design.

With the introduction of the subgrid value for grid-template-rows and grid-template-columns, grid children can now inherit the grid row and column settings from the parent and properly position their own children in a smooth and effortless way, without requiring any additional configuration from the code author.

The previous issue is solved simply by passing the subgrid value to grid-template-columns on all .card elements, as seen in Kevin Powell's solution pen.

1
.card {
2
  display: grid;
3
  grid-template-columns: subgrid
4
}

By setting the value of subgrid for all .card elements, they'll completely follow the column configurations of the main grid, which means other spacing properties like gap (formerly grid-gap) will be inherited, and will automatically update whenever the parent configuration is changed.

When Can You Use subgrid?

At the time of writing, the new subgrid value is almost fully supported on Firefox. While other major browsers are yet to support it, they won’t be far behind.

Conclusion

CSS Grid has tons of rules, and I only covered the most useful ones in this tutorial. You can still dig into MDN Web Docs or any other sources for the full list of grid properties and functions.

This post has been updated with contributions from Kingsley Ubah. Kingsley is passionate about creating content that educates and inspires readers. Hobbies include reading, football and cycling.

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.