Menu

CSS Grid Layout: Columns, Rows, fr, gap and Areas

CSS grid lays out items in rows and columns at once. Learn display: grid, grid-template-columns, the fr unit, repeat() and minmax(), auto-fill vs auto-fit, placing items with grid-column, and grid-template-areas, with a live grid you edit and measure.

This page includes runnable editors - edit, run, and see output instantly.

A grid in three lines

Set display: grid on a container and list its columns with grid-template-columns. The children fill the cells in order, left to right in English, and a new row starts whenever the columns are full:

Seven items, three columns: two full rows and a third row with item 7 in the first column. Every column is the same width, and every item in a row is the same height, so the edges line up in both directions. That is what grid adds over flexbox.

Grid playground

Type any grid-template-columns value, or click a preset. The readout shows the column widths the browser worked out (from getComputedStyle) and how many rows the items needed:

Some things to see: 1fr 2fr makes the second column exactly twice the first. 200px 1fr keeps 200px and gives the rest to the second column. auto 1fr auto sizes the outer columns to their content. repeat(4, 100px) leaves empty space at the end because nothing is flexible. An invalid value, such as 1fr 2, is ignored, and the grid keeps the last valid value.

The fr unit

fr means "one share of the free space". The browser first takes out fixed columns (px, rem, %, auto content) and the gaps, then splits what is left between the fr columns by their numbers.

grid-template-columns in a 600px container, no gapColumn widths
1fr 1fr 1fr200, 200, 200
1fr 2fr200, 400
100px 1fr 1fr100, 250, 250
1fr 50%300, 300

fr is not the same as %: percentages plus gaps can add up to more than 100% and overflow, while fr columns always share only what is left after the gaps.

repeat(), minmax() and a responsive grid with no media queries

repeat(4, 1fr) is 1fr 1fr 1fr 1fr. minmax(120px, 1fr) is a column that is never narrower than 120px and grows to take a share. Put them together with auto-fill or auto-fit in place of a count, and the grid creates as many columns as fit:

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

That one declaration gives as many columns of at least 180px as the container fits: several on a wide screen, one on a phone, with no media query. The difference between auto-fill and auto-fit shows when there are fewer items than columns:

The container fits five 100px columns. auto-fill keeps all five, so A, B and C are 112px each and two empty columns remain. auto-fit collapses the empty ones, so the three items stretch to about 187px each.

Placing items: grid-column and grid-row

Grid lines are numbered from 1 at the start edge. grid-column: 1 / 3 means "from line 1 to line 3", which is two columns. span 2 means "two columns from wherever you land", and -1 is the last line:

The dark item fills the whole first row. The blue one covers a 2 by 2 block, the amber one two rows. Items a and b fill the remaining cells on their own: grid places every item it can into the next free cell. grid-auto-rows: 60px sets the height of rows you did not declare with grid-template-rows.

grid-template-areas: name the parts of a layout

For a page layout, name the areas and draw them as text. Each string is a row, each word a cell, and an item joins an area with grid-area:

The header and footer span both columns because their names fill both cells of their rows. The middle row is 1fr, so it takes whatever height is left of the 280px. To stack everything on a phone, a media query only has to redraw the areas as one column: grid-template-areas: "header" "side" "main" "footer" with grid-template-columns: 1fr. The media queries page shows the pattern.

Aligning inside the cells

Grid items stretch to fill their cell by default. These properties move them inside it:

PropertyOnMoves
justify-itemscontainerevery item along the row (inline axis)
align-itemscontainerevery item up and down (block axis)
place-itemscontainershorthand: place-items: center centers in both
justify-self / align-selfitemone item
justify-content / align-contentcontainerthe whole set of tracks, when the grid is smaller than the container

display: grid; place-items: center; is the shortest way to center one child in a box.

Grid or flexbox

Grid is two dimensional: you decide the columns (and rows), and the content fills them, so every card in a gallery has the same width even on the last row. Flexbox is one dimensional: items size themselves from their content along a single line. They mix well: a grid for the page and the card gallery, flexbox inside each card for its header row. The flexbox page covers the other half.

Order and accessibility

grid-template-areas, grid-row, grid-column and order can place an item anywhere, but screen readers and the Tab key still follow the HTML order. Keep the source order meaningful (header, navigation, main, footer) and use grid to arrange it, not to fix an HTML order that makes no sense.

Common mistakes

  • Putting display: grid on the items. It goes on the parent; only direct children are grid items.
  • Using percentages with gaps. grid-template-columns: 50% 50% plus gap: 16px overflows by 16px. Use 1fr 1fr.
  • auto-fill when you wanted auto-fit. With few items, auto-fill leaves empty columns. Switch to auto-fit to stretch the items.
  • A 1fr column that grows past its share. A 1fr column will not shrink below its longest content (a long URL, a wide image). Use minmax(0, 1fr) to let it shrink.
  • Area strings that are not rectangles. Every named area must form a rectangle, and every row string needs the same number of cells, or the whole grid-template-areas declaration is ignored.
  • Forgetting that line numbers start at 1. Three columns have four lines: 1 / 4 or 1 / -1 spans all three.

Frequently Asked Questions

What is CSS grid?

A layout system that places elements in rows and columns at the same time. You set display: grid on a container, describe its columns with grid-template-columns (and optionally its rows), and its direct children fill the cells in order.

What does 1fr mean in CSS grid?

fr is a fraction of the free space in the grid container. grid-template-columns: 1fr 1fr 1fr gives three equal columns, and 1fr 2fr makes the second column twice as wide as the first. Fixed sizes and gaps are taken out first; the fr columns share what is left.

What is the difference between auto-fill and auto-fit?

Both create as many columns as fit. auto-fill keeps the empty columns, so a few items stay narrow and leave empty space at the end of the row. auto-fit collapses the empty columns, so the items stretch to fill the row. With enough items to fill the row, the two look the same.

How do I make a grid item span two columns?

Use grid-column: span 2 on the item, or give it start and end lines: grid-column: 1 / 3 covers columns 1 and 2. grid-column: 1 / -1 spans the full width, because -1 is the last line.

When should I use grid instead of flexbox?

Use grid when rows and columns must line up with each other: card galleries, forms with aligned labels, a page with a header, sidebar and footer. Use flexbox for a single row or column whose items size themselves from their content, such as a nav bar.

Is grid-gap the same as gap?

Yes. grid-gap, grid-row-gap and grid-column-gap are the old names. Browsers still accept them as aliases, but write gap, row-gap and column-gap, which also work in flexbox.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED