Tips・Cheat sheets

CSS Grid cheatsheet

The quick reference that answers "what is 1fr again?" and "how does repeat work?" Every Grid property you actually use, with live demos you can switch values on. Includes the go-to card-list recipe.

CSS Grid is the shortest route to card lists and page skeletons—yet 1fr and repeat(auto-fit, minmax(...)) are exactly the kind of thing you can never quite recall. This article is a quick reference to the Grid properties you actually use, with live demos.

CSSLine things up in a Grid with GridLearning Grid for the first time? Start with this lesson of the CSS course. This article is for remembering

The whole map

Grid’s properties, like Flexbox’s, come in two kinds: the ones you put on the parent (the container) and the ones you put on a child (an item).

Where it goesPropertyWhat it does
Parentdisplay: gridThe starting signal
Parentgrid-template-columnsThe number and width of columns
Parentgrid-template-rowsThe number and height of rows
ParentgapThe space between cells
Parentjustify-itemsHorizontal alignment inside each cell
Parentalign-itemsVertical alignment inside each cell
Parentgrid-template-areasName the cells and place by name
Childgrid-columnWhich columns it spans
Childgrid-rowWhich rows it spans
Childjustify-self / align-selfChange alignment for this one only

In practice, grid-template-columns and gap cover 80%. Get those and you can start building.

grid-template-columns—the blueprint for columns

The star of the show. You write “how many columns, at what widths,” separated by spaces. Press the buttons and compare how the values behave.

Cells line up across for as many columns as you declared, and when they run out, they move to the next row automatically. So “six boxes in two columns” gives you three rows without you counting. You never declare the row count.

The fr unit

fr is short for fraction, and it means “a unit for sharing out the space that’s left.” It is not a fixed length like px.

What you writeWhat it means
1fr 1frHalf and half
2fr 1frSplit two to one
100px 1frFirst column fixed at 100px, second takes the rest
1fr autoFirst column stretches, second is as wide as its content

“px for columns you want fixed, fr for columns you want to stretch”—that’s the most common shape in Grid. A sidebar-plus-main two-column layout is done with 240px 1fr.

repeat()—shorten a repeated pattern

Repetition like 1fr 1fr 1fr 1fr can be collapsed with repeat().

.grid {
  grid-template-columns: repeat(3, 1fr);        /* 1fr three times = 3 equal columns */
  grid-template-columns: repeat(2, 100px 1fr);  /* 100px 1fr twice = 4 columns */
}

The first argument is how many times, the second is what to repeat. Change the count in one place and you’re done.

Responsive without media queries

This is the single most rewarding thing to learn in Grid: a way to write columns that change count with the screen width, on their own.

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

Read it like this.

  • minmax(240px, 1fr)—one card is “at least 240px, at most a share of what’s left
  • auto-fit—place as many as fit under that rule, and wrap when they don’t

So the judgement “if it would go under 240px, use fewer columns” is made by the browser. That one line finishes phone support for a card list. Drag the width in the demo below to see it.

gap—the space between cells

.grid {
  gap: 16px;         /* 16px both ways */
  gap: 24px 16px;    /* 24px between rows, 16px between columns */
}

Unlike spacing each item with margin, this leaves no stray space on the outside. If you’re using Grid, hand your spacing to gap.

grid-template-rows—row heights

Rows work the same way as columns. Leave it out and rows are sized to their content.

.layout {
  grid-template-rows: 80px 1fr 60px;   /* header, body, footer */
  min-height: 100vh;
}

Putting 1fr in the middle gives you the layout where the footer sticks to the bottom even when there’s little content.

Properties for children

grid-column / grid-row—span across cells

For “just this one card should take two columns.” span is the readable form.

.wide {
  grid-column: span 2;    /* two cells across */
}
.tall {
  grid-row: span 2;       /* two cells down */
}

You can also name the grid lines. grid-column: 1 / 3 means “from line 1 to line 3,” which is two cells. You count the lines, not the cells—that’s Grid’s mental model, and the first thing that trips people up.

.hero {
  grid-column: 1 / -1;    /* from the first line to the last = full width */
}

-1 means “the rightmost line,” a handy way to stay full width even when the column count changes.

justify-self / align-self—change alignment for one item

Override the position within its own cell, for that child only.

.item {
  justify-self: center;   /* horizontally centred in its cell */
  align-self: end;        /* bottom-aligned in its cell */
}

grid-template-areas—place by name

For a whole-page skeleton, naming the cells and drawing the layout reads beautifully.

.layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "header header"
    "side   main"
    "footer footer";
  gap: 16px;
}
.layout > header { grid-area: header; }
.layout > aside  { grid-area: side; }
.layout > main   { grid-area: main; }
.layout > footer { grid-area: footer; }

The strength is that the CSS shows you the shape of the layout. To rearrange it for phones, you rewrite grid-template-areas inside a media query and nothing else.

Five recipes you can use as-is

A responsive card list

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

Sidebar plus main content

.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 24px;
}
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}
.gallery img {
  width: 100%;
  aspect-ratio: 1 / 1;     /* make it square */
  object-fit: cover;       /* crop the overflow */
}

Make one item big

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}
.cards .featured {
  grid-column: 1 / -1;     /* full width */
}

Dead centre

.center {
  display: grid;
  place-items: center;      /* justify-items and align-items in one */
  min-height: 100vh;
}

place-items: center is the shortest way to centre both ways in one line. What took two lines in Flexbox takes one here.

Flexbox or Grid?

What you’re buildingThe better fit
A nav menu or a row of buttonsFlexbox
A header (logo left, menu right)Flexbox
A card listGrid
The whole page skeletonGrid
A photo galleryGrid
A row whose widths follow the contentFlexbox
Cells that must line up in both directionsGrid

Roughly: one direction is Flexbox, a grid of cells is Grid. When in doubt, decide on whether the columns need to line up. Flexbox doesn’t line up columns across wrapped rows; Grid always does.

TipsFlexbox cheat sheetThe Flexbox cheatsheet, with live demos

Checklist when Grid isn’t working

  • Nothing lines updisplay: grid goes on the parent of the things you’re arranging
  • gap does nothinggap also goes on the parent
  • Some child isn’t in a cell → only the direct children of the element with display: grid land in cells. Have you wrapped them in an extra div?
  • Columns overflow → are you adding up to 100% with % or px? Switching to fr subtracts the gap for you
  • align-items does nothing → if the row is exactly as tall as its content, there’s nothing to align within. Check grid-template-rows or min-height
  • An image bursts out of its cell → give images max-width: 100% (or width: 100%). A grid cell won’t shrink below its content’s minimum width, so a large image widens the column

Summary

  1. Learn grid-template-columns and gap first—they cover 80% of the work
  2. fr is a unit for sharing out what’s left; unlike %, it never overflows when combined with gap
  3. repeat(auto-fit, minmax(240px, 1fr)) gives you a card list with no media queries
  4. For a full-width child, grid-column: 1 / -1. Counting lines is Grid’s mental model
  5. One direction is Flexbox; if the cells must line up, it’s Grid
TipsCopy-and-paste CSS card designsFor the look of the cards themselves, see the copy-paste design collection

Lining up columns is work best handed to Grid. Write it once for a card list, and your fingers will remember it after that.

FAQ

What does the "fr" in 1fr mean?
It's short for fraction—a unit for sharing out the space that's left over. 1fr 1fr splits it in half; 2fr 1fr splits it two to one. It isn't an absolute length like px; it's a ratio of the remaining space.
How do I choose between Flexbox and Grid?
Flexbox for laying things out in one direction (a single row or column), Grid for placing things on a two-dimensional set of cells. Menus and button rows are Flexbox; card lists and the overall page skeleton are Grid.
I want the number of card columns to change with the screen width
Write grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); and the column count changes on its own, with no media queries. The 240px is the minimum width of one card: as many as fit are placed, and it wraps when they no longer fit.
gap isn't working
gap goes on the parent (the grid container). It does nothing on a child. Also, only the direct children of the element with display: grid land in cells, so check you haven't wrapped them in an extra div.