CSS Grid Layout

CSS Grid Layout
udemy2 placeholder image

For years, CSS has been infamous for the difficulty of designing a grid layout for a page. Solutions definitely existed, and things like Bootstrap were created to help, but they always felt hacky and excessive. CSS Grid aims to fix this situation by offering a native grid layout system. With CSS Grid, you can easily and beautifully define a two-dimensional grid layout using less markup and less styles.

Terminology

Before we get into learning how to use CSS Grid, there's some terminology that we should become familiar with.

Grid Lines

Grid lines are the lines that make up the grid. They divide up the entire area into rows and columns.

Diagram showing a Grid line.
Diagram showing a Grid line.

Grid Cell

A grid cell is a single unit in the grid formed from the grid lines. Essentially, it just means one box.

Diagram showing a Grid cell.
Diagram showing a Grid cell.

Grid Area

A grid area is the rectangular space formed between different horizontal and vertical grid lines.

Diagram showing a Grid area.
Diagram showing a Grid area.

Grid Row

A grid row is all the grid cells between two consecutive horizontal grid lines.

Diagram showing a Grid row.
Diagram showing a Grid row.

Grid Column

A grid column is all the grid cells between two consecutive vertical grid lines.

Diagram showing a Grid column.
Diagram showing a Grid column.

Grid Gap

A grid gap is the gap of space between rows and columns. Alternatively, this is the space between grid cells.

Diagram showing a Grid gap.
Diagram showing a Grid gap.

Getting Started

Now that we have the terminology down, let's get started on making our first CSS grid. For simplicity's sake, let's create a 3 by 2 grid. That is to say a grid with 3 columns and 2 rows. Let's start with the markup:

	
    <div class="container">
    	<div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
        <div class="cell"></div>
    </div>
	

To define a grid, we must use the display property with a value of grid:

	
    .container {
        display: grid;
    }
	

The way to define rows and columns is using the grid-template-columns and grid-template-rows properties. What you provide as the value is the width or height of each of the rows and columns. Every value provided creates a new row or column. Let's say we wanted squares each 200px in length:

	
    .container {
        display: grid;
        grid-template-columns: 200px 200px 200px;
        grid-template-rows: 200px 200px;
    }
	

Since we passed in three values for grid-template-columns, three columns were created, each 200px wide. We also passed in two values for grid-template-rows, each 200px tall.

Here is our grid so far:

	
    <!DOCTYPE html>
    <html>
        <head>
            <title>Grid</title>
            <style>
                .container {
					display: grid;
					grid-template-columns: 200px 200px 200px;
					grid-template-rows: 200px 200px;
				}
				.cell {
					background-color: lightblue;
                    border: solid 1px blue;
				}
            </style>
        </head>
        <body>
			<div class="container">
				<div class="cell"></div>
			    <div class="cell"></div>
			    <div class="cell"></div>
			    <div class="cell"></div>
			    <div class="cell"></div>
			    <div class="cell"></div>
			</div>
        </body>
    </html>
	
Our first CSS grid!
Our first CSS grid!

Grid Gap

Because we have yet to define a grid gap, all of the grid cells are touching one another. Let's fix that by defining a grid gap. This is done with the grid-gap property where the value is two lengths, one for the row and the other for the column. If you just pass in a single value, it will apply it to both the rows and columns.

	
    .container {
        display: grid;
        grid-template-columns: 200px 200px 200px;
        grid-template-rows: 200px 200px;
        grid-gap: 1rem;
    }
	

With the new grid gap, our grid now looks like this:

A CSS grid with a grid gap.
A CSS grid with a grid gap.
namecheap placeholder image

FR (Fraction) Unit

So far our grid looks good, however we defined it using static lengths. It works, but it isn't responsive nor flexible at all. Along with CSS Grid comes a new unit specifically for this called fraction. The unit is used relative to how much space is left in the row or column. That means that 1fr takes up 100% of the remaining space. However, this is also relative to other cells, so if we set all our columns to 1fr the browser will just evenly divide up the space, giving us equally-spaced columns:

	
    .container {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-template-rows: 200px 200px;
        grid-gap: 1rem;
    }
	
A CSS grid using the fr unit.
A CSS grid using the fr unit.

Because we gave each of our three columns a width of 1fr the browser divided up the remaining space by three. The row height, left untouched from before, simply remained the same at 200px.

As you might expect, you can even mix and match units and the browser will do the hard work for you. Let's say you wanted the first column to be 150px, the second column to take up 20% of whatever is left, and then the third column take whatver is left of that:

	
    .container {
        display: grid;
        grid-template-columns: 150px 20% 1fr;
        grid-template-rows: 100px 100px;
        grid-gap: 1rem;
    }
	
A CSS grid using mixed units.
A CSS grid using mixed units.

Grid Start and End

We've seen just how much control we have over our grids. We can determine the number of rows and columns, how tall or wide they should be and how much space should be in between two cells. However, CSS offers us even more control.

So far our items have just been populated in the order they appear in our markup, but we have the power to control that by defining at what lines an item starts and ends at. Before we go any further, let's look at a diagram that shows how CSS defines lines across rows and columns:

All the lines on a grid.
All the lines on a grid.

Pretty simple, right? From the top-left corner, the lines start at 1 and move up as you go across and down. That means that the first cell in the diagram starts at row line 1 and ends at row line 2, and starts at column line 1 and ends at column line 2. As another example, the bottom-right-most cell starts at row line 2 and ends at row line 3, and starts at column line 3 and ends at column line 4.

As you would expect, there are CSS properties to define this and they are called grid-row and grid-column. Let's see this in action by making the first element render in the the middle bottom spot:

	
    <div class="container">
		<div class="cell special">1</div>
	    <div class="cell">2</div>
	    <div class="cell">3</div>
	    <div class="cell">4</div>
	    <div class="cell">5</div>
	    <div class="cell">6</div>
	</div>
	
	
    .container {
        display: grid;
        grid-template-columns: 100px 100px 100px;
        grid-template-rows: 100px 100px;
        grid-gap: 1rem;
    }
    .cell {
        background-color: lightblue;
        border: solid 1px blue;
        line-height: 100px;
        text-align: center;
    }
    .special {
        grid-row: 2 / 3;
        grid-column: 2 / 3;
    }
	
Showing the use of grid-row and grid-column.
Showing the use of grid-row and grid-column.

As expected, since we gave the first cell the special class which had grid-row and grid-column defined, it was placed in the spot we told it to be at, instead of at the top left position. The other cells then filled in the space in the order they would have normally.

Named Grid Lines

While it was easy enough to reference the grid lines on our grid, it might not be so straightforward on a bigger or more complex grid. Thankfully, CSS allows us to give the lines a name so that we can reference them that way instead of by their number. It makes the grid easier to comprehend and maintain.

For simplicity's sake, let's use the same example as before, putting the first cell in a new position, but do so with a named line instead:

	
    <div class="container">
		<div class="cell special">1</div>
	    <div class="cell">2</div>
	    <div class="cell">3</div>
	    <div class="cell">4</div>
	    <div class="cell">5</div>
	    <div class="cell">6</div>
	</div>
	
	
    .container {
        display: grid;
        grid-template-columns:
          [column-1] 100px
          [column-2] 100px
          [column-3] 100px
          [column-4];
        grid-template-rows:
          [row-1] 100px
          [row-2] 100px
          [row-3] 100px
          [row-4];
        grid-gap: 1rem;
    }
    .cell {
        background-color: lightblue;
        border: solid 1px blue;
        line-height: 100px;
        text-align: center;
    }
    .special {
        grid-row: row-2 / row-3;
        grid-column: column-2 / column-3;
    }
	
Moving an item using named lines.
Moving an item using named lines.

While in this example we are still using numbers in their names, nothing stops you from renaming row-3 to peanut-butter if you wanted to. The point here is that you aren't forced to try and keep track of the row and column line numbers to build out your grid. Just give them names and then reference them in your styles!

namecheap placeholder image

Template Areas

An arguably easier way to define a grid layout and where items start and end is with the use of template areas. With template areas, you just tell the browser how to layout your grid using plain written language. You literally give the different cells in your grid a unique name and define where it belongs relative to the other cells.

Let's say you wanted a grid where the top and bottom boxes covered an entire row, but the middle row was split across two different columns:

	
    <div class="container">
		<div class="cell top">1</div>
	    <div class="cell middle-1">2</div>
	    <div class="cell middle-2">3</div>
	    <div class="cell bottom">4</div>
	</div>
	
	
    .container {
        display: grid;
        grid-template-columns: 100px 100px;
        grid-template-rows: 100px 100px;
        grid-gap: 1rem;
        grid-template-areas:
          "top 		top"
          "middle-1 middle-2 "
          "bottom 	bottom";
    }
    .cell {
        background-color: lightblue;
        border: solid 1px blue;
        line-height: 100px;
        text-align: center;
    }
    .top {
        grid-area: top;
    }
    .middle-1 {
        grid-area: middle-1;
    }
    .middle-2 {
        grid-area: middle-2;
    }
    .bottom {
        grid-area: bottom;
    }
	
Showing the use of grid-template-areas.
Showing the use of grid-template-areas.
  • HTML
  • CSS
Run

How cool is that? No need to mess with numbers at all. You literally define your grid inside the value of grid-template-areas, pass along the grid-area properties to the cells, and the browser takes care of the rest.

The magic is all in here:

	
    grid-template-areas:
      "top 		top"
      "middle-1 middle-2 "
      "bottom 	bottom";
	

Conclusion

A CSS Grid is a powerful and native way to define all kinds of grid layouts, from the simpliest and basic to the more complex and sophisticated. The cool part is that they can even be used in conjunction with flexible boxes for even more control over your page!

Now building grids is as easy as playing with Legos!
Now building grids is as easy as playing with Legos!

Resources