Grid: laying things out in two dimensions

Introduction

Flexbox arranges things along one line. A page, though, has columns and rows that need to line up with each other, and that is what CSS Grid does. It lets you draw the whole layout in one place, and then drop items into it.

How it works

Add display: grid to a container. Its direct children become grid items, which you arrange on rows and columns called tracks.

Defining columns. grid-template-columns lists the width of each column:

.page { display: grid; grid-template-columns: 200px 1fr 1fr; gap: 16px; }

The fr unit means a share of the free space. Here the first column takes 200px, and the two others split what is left equally. That is hard to do with percentages once gaps are involved, because percentages do not know about the gap.

repeat(3, 1fr) is a shorter way to write 1fr 1fr 1fr. Rows work the same way, with grid-template-rows. If you do not define them, rows are created automatically to fit the content.

Placing items. Items fill the grid in order, one cell at a time. To control one, refer to the numbered lines between the tracks, which begin at 1:

.wide { grid-column: 1 / 3; }   /* from line 1 to line 3 */
.tall { grid-row: span 2; }     /* two rows, from wherever it lands */

grid-column: 1 / -1 stretches all the way across, since negative numbers count from the end.

Named areas are a very readable way to set out a whole page:

.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "header header"
    "side   main";
}
header { grid-area: header; }

Each string is a row, and each word is a cell. A dot means an empty cell. Each area must be a rectangle.

Responsive with no media queries. This one line is worth remembering:

grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));

minmax(200px, 1fr) means a column is never narrower than 200px, and may grow to share the space. auto-fit fits as many as will go in a row. Cards then rearrange themselves at any width.

Alignment uses the same words as flexbox. justify-items aligns within a cell horizontally, and align-items vertically.

Grid or flexbox? They are partners. Use grid when you are planning rows and columns together, such as a page or a gallery. Use flexbox when content runs in one direction, such as a toolbar. A grid cell often contains a flex row.

Syntax

.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

Example

console.log output from the page shows here.

Line by line

  1. grid-template-columns creates a 120px column and a flexible one.
  2. grid-template-areas draws the layout using three strings, one for each row.
  3. Each element is sent to its area with grid-area.
  4. .page > * gives every direct child some padding and a background.

Expected result

A full-width header, a narrow menu beside a wide main area, and a full-width footer.

In the real world

Dashboards, photo galleries and magazine layouts rely on grid. The auto-fit pattern is used everywhere for product and course cards, and many of the card lists on this site are built the same way.

Common mistakes

  • Trying to use percentages along with gaps, and overflowing.
  • Forgetting that lines start at 1.
  • Writing a non-rectangular area, which invalidates the whole template.
  • Using grid for a simple row that flexbox would handle.

Best practices

  • Prefer fr to percentages.
  • Use named areas for page structure.
  • Use gap rather than margins on items.
  • Combine grid and flexbox freely.

Summary

Grid arranges items in rows and columns. fr shares free space, repeat and minmax shorten definitions, lines position items, and named areas describe whole layouts. auto-fit with minmax makes grids responsive automatically.

Quick check

1. In grid-template-columns: 100px 1fr 1fr, on a 500px grid with no gap, how wide is each 1fr column?
2. What does grid-column: 1 / -1 do?
3. When is grid a better choice than flexbox?

Key takeaways

  • Grid controls rows and columns together.
  • fr shares out the space that remains after fixed sizes are taken.
  • Lines are counted from 1, and an item can span several tracks.
  • repeat(auto-fit, minmax(...)) creates responsive grids by itself.

Practice problems for this lesson

My notes

Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.