How to Create a Grid Layout Using CSS

For more complex layouts, you can opt to use a grid system.

A grid layout consists of a grid container and several grid items. The grid container must have its display property set to grid or inline-grid. grid creates a block-level container, and inline-grid creates an inline-level container.

html
1<div class="container">
2  <div class="item">1</div>
3  <div class="item">2</div>
4  <div class="item">3</div>
5  <div class="item">4</div>
6  <div class="item">5</div>
7  <div class="item">6</div>
8</div>
css
1.container {
2  display: grid;
3}

All direct children of this container will automatically become grid items.

Grid columns

Open demo in new tab
Hint: You can edit this CodePen demo directly.

You can then specify how many columns you wish to create using the grid-template-columns property. The property accepts any number of values. The number of values determines the number of columns, and the value itself determines the size of that column. For example:

css
1.container {
2  display: grid;
3  grid-template-columns: 100px 200px;
4}
5
6.item {
7  font-family: Georgia, "Times New Roman", Times, serif;
8  font-size: x-large;
9  text-align: center;
10  padding: 20px;
11  border: 1px solid orange;
12  background-color: bisque;
13}

grid with two columns

We also added some styles for the grid items to make the grid look more pleasing, but it is not necessary for the purpose of this lesson, so they will be omitted in future examples.

In this example, we created two columns, the first one is 100px wide, and the second one is 200px wide. If you want more columns, simply add more values.

css
1.container {
2  display: grid;
3  grid-template-columns: 100px 200px 50px;
4}

grid with three columns

If you want all columns to be equal in size, set the value to auto.

css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4}

grid with auto columns

This will allow the browser to choose an appropriate column size to fill the parent container.

Grid rows

Open demo in new tab

The grid rows, on the other hand, are created automatically. You can define row sizes using the grid-template-rows property.

css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4  grid-template-rows: 100px 150px;
5}

grid with different row heights

However, this property does not determine the number of rows in the grid. It only controls the row height. If you specify extra values, they will be ignored.

This is because, by default, the grid items will flow horizontally, meaning they will fill the first row, and if there is insufficient space, the remaining items will be moved to the second row, and so on.

Grid flow

Open demo in new tab

This default behavior is a bit problematic because sometimes, you only know how many rows you want, and you need the browser to create the columns automatically. In this case, you can change the flow direction of the grid items by setting grid-auto-flow to column.

Next, you can configure the gird rows, and this time, you can define the number of rows, as well as their sizes. The columns, on the other hand, will be created automatically.

css
1.container {
2  display: grid;
3  grid-auto-flow: column;
4
5  grid-template-rows: 100px 100px;
6  grid-template-columns: 100px 200px 300px;
7}

The grid template shorthand

Lastly, grid-template is a shorthand property for grid-template-columns and grid-template-rows with the following syntax:

text
1grid-template: <row> <row> ... / <col> <col> ...;
css
1.container {
2  display: grid;
3  grid-template: 100px 150px / auto auto auto;
4}

grid template

Grid gaps

Open demo in new tab

When designing a webpage, it is good to leave some space between elements so that they are not too close to each other. By using the grid layout, you can easily add equal spacing between the grid items instead of micromanaging their individual margin. For example:

css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4  row-gap: 10px;
5  column-gap: 20px;
6}

gaps

Alternatively, you may use the shorthand property, gap:

css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4  gap: 10px 20px;
5}

If you want equal spacing for columns and rows, give a single value:

css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4  gap: 10px;
5}

gaps with equal spacing

Spanning over multiple columns

Open demo in new tab

You can also customize individual grid items using CSS. In a real-life scenario, it is common for one grid item to take up multiple columns or rows. For example, you can define an item to span multiple columns by specifying a start point (grid-column-start) and an end point (grid-column-end).

html
1<div class="container">
2  <div class="item-2col">1</div>
3  <div class="item">2</div>
4  <div class="item">3</div>
5  <div class="item">4</div>
6  <div class="item">5</div>
7  <div class="item">6</div>
8  <div class="item">7</div>
9  <div class="item">8</div>
10</div>
css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4  gap: 10px;
5}
6
7.item {
8  /* . . . */
9}
10
11.item-2col {
12  grid-column-start: 1;
13  grid-column-end: 3;
14}

grid item two columns

Keep in mind that the numbers refer to the column line, not the column itself, as shown in the chart below.

column lines and row lines

As a result, for an item to span over two columns, it should start from 1 and end with 3.

You can also use the shorthand property grid-column to achieve the same result:

css
1.item-2col {
2  grid-column: 1 / 3;
3}

Instead of counting the grid lines, you can specify the number of columns you want the item to span over, and the browser will calculate the grid lines automatically.

css
1.item-2col {
2  grid-column: span 2;
3}
4
5.item-3col {
6  grid-column: span 3;
7}
Open demo in new tab

Spanning over multiple rows

Similarly, you can define a grid item to span across multiple rows using the grid-row-start and grid-row-end properties, or the grid-row shorthand.

css
1.item-2row {
2  grid-row-start: 1;
3  grid-row-end: 3;
4}
css
1.item-2row {
2  grid-row: 1 / 3;
3}

grid row

Spanning over an area

If an item needs to span over multiple rows and columns, you can use the grid-area property instead, which is a shorthand for grid-row and grid-column. The property has the following syntax:

text
1grid-area: <row_start> / <col_start> / <row_end> / <col_end>
css
1.item-area {
2  grid-area: 1 / 1 / 3 / 3;
3}

grid area

Nested grid systems

In practice, you might need a more complex layout for your webpages. For example, your website might have a general layout with a header, footer, main content, as well as a sidebar.

html
1<div class="container">
2  <div class="nav">Navbar</div>
3  <div class="main">Main</div>
4  <div class="sidebar">Sidebar</div>
5  <div class="footer">Footer</div>
6</div>
css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4}
5
6.container div {
7  font-family: Georgia, "Times New Roman", Times, serif;
8  font-size: x-large;
9  text-align: center;
10  padding: 20px;
11  border: 1px solid orange;
12  background-color: bisque;
13}
14
15.nav {
16  grid-column: 1 / 4;
17}
18
19.main {
20  grid-column: 1 / 3;
21  height: 50vh;
22}
23
24.sidebar {
25  grid-column: 3 / 4;
26  height: 50vh;
27}
28
29.footer {
30  grid-column: 1 / 4;
31}
Open demo in new tab

And inside the main content section, you might need a 3x3 grid for your blog articles, and inside the sidebar, you might need another grid for the subsections.

html
1<div class="container">
2  <div class="nav">Navbar</div>
3  <div class="main">
4    <div class="post">Post</div>
5    <div class="post">Post</div>
6    <div class="post">Post</div>
7    <div class="post">Post</div>
8    <div class="post">Post</div>
9    <div class="post">Post</div>
10  </div>
11  <div class="sidebar">
12    <div class="section">Section</div>
13    <div class="section">Section</div>
14    <div class="section">Section</div>
15  </div>
16  <div class="footer">Footer</div>
17</div>
css
1.container {
2  display: grid;
3  grid-template-columns: auto auto auto;
4}
5
6.container div {
7  font-family: Georgia, "Times New Roman", Times, serif;
8  font-size: x-large;
9  text-align: center;
10  padding: 20px;
11  border: 1px solid orange;
12  background-color: bisque;
13}
14
15.nav {
16  grid-column: 1 / 4;
17}
18
19.main {
20  grid-column: 1 / 3;
21  height: 50vh;
22
23  display: grid;
24  grid-template-columns: auto auto auto;
25  gap: 10px;
26}
27
28.sidebar {
29  grid-column: 3 / 4;
30  height: 50vh;
31
32  display: grid;
33  grid-template-columns: auto;
34  gap: 10px;
35}
36
37.footer {
38  grid-column: 1 / 4;
39}
Open demo in new tab

As you can see, this system isn't simple. As the webpage becomes increasingly complex, this grid system will become quite messy and difficult to maintain.

A better way to do things is to have a universal grid system. You can make sure all grid systems have 12 columns, and you only have to worry about how many columns each item has to span over.

For example, you can redesign the general layout of the webpage like this:

html
1<div class="grid">
2  <div class="col-span-12">Nav</div>
3  <div class="col-span-8">Main</div>
4  <div class="col-span-4">Sidebar</div>
5  <div class="col-span-12">Footer</div>
6</div>
css
1.grid {
2  display: grid;
3  grid-template-columns: repeat(12, auto);
4  gap: 10px;
5}
6
7.grid div {
8  font-family: Georgia, "Times New Roman", Times, serif;
9  font-size: x-large;
10  text-align: center;
11  padding: 20px;
12  border: 1px solid orange;
13  background-color: bisque;
14}
15
16.col-span-1 {
17  grid-column: span 1;
18}
19
20/* . . .  */
21
22.col-span-12 {
23  grid-column: span 12;
24}

The best part about this system is that the defined grid styles can be reused. You can use it to create the 3x3 blog grid.

html
1<div class="col-span-8 grid">
2  <div class="col-span-4">Post</div>
3  <div class="col-span-4">Post</div>
4  <div class="col-span-4">Post</div>
5  <div class="col-span-4">Post</div>
6  <div class="col-span-4">Post</div>
7  <div class="col-span-4">Post</div>
8  <div class="col-span-4">Post</div>
9  <div class="col-span-4">Post</div>
10  <div class="col-span-4">Post</div>
11</div>

Or the sidebar:

html
1<div class="col-span-4 grid">
2  <div class="col-span-12">Section</div>
3  <div class="col-span-12">Section</div>
4  <div class="col-span-12">Section</div>
5</div>
Open demo in new tab