Skip to main content
Back to module
HTML & CSS Foundations · Responsive Pages

Grid layout

Reading1h 10mLesson 1 of 3 in this module

Build a full page layout and a responsive gallery with CSS Grid, template areas and the fr unit.

Why this matters

Flexbox arranges items along one line. Many layouts are two-dimensional: a header across the top, a sidebar and main area side by side, a footer at the bottom, or a gallery of tiles in rows and columns. CSS Grid is built for that. It lets you describe the whole layout on the parent, in a way that reads almost like a drawing.

The core idea: tracks on the container

.gallery {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1rem;
}
  • display: grid makes the element a grid container; its direct children become grid items.
  • grid-template-columns defines the column tracks. Here: three equal columns.
  • Items flow into the cells automatically, left to right, then onto the next row.
  • gap sets the space between rows and columns.

The fr unit

fr means "a fraction of the remaining space". After fixed tracks and gaps are subtracted, the leftover space is shared in proportion:

grid-template-columns: 200px 1fr;     /* fixed sidebar, flexible main area */
grid-template-columns: 2fr 1fr;       /* main area twice as wide as the side */
grid-template-columns: repeat(4, 1fr); /* four equal columns */

repeat(4, 1fr) is shorthand for 1fr 1fr 1fr 1fr.

Template areas: drawing the layout

For page layouts, name the regions and draw them as a map:

.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
}

.site-header { grid-area: header; }
.sidebar     { grid-area: sidebar; }
.content     { grid-area: main; }
.site-footer { grid-area: footer; }
  • Each quoted string is one row; each word is one column cell.
  • Repeating a name ("header header") makes that area span both columns.
  • grid-template-rows: auto 1fr auto sizes the header and footer to their content and gives the middle row the remaining height, so with min-height: 100vh the footer sits at the bottom of the screen even on a short page.
  • Each item claims its area with grid-area.

Areas must form rectangles; an L-shaped area is invalid and the whole template is ignored. A . in the map leaves a cell empty.

Placing items by line number

Grid lines are numbered from 1 at the start edge. You can place an item across lines directly:

.feature {
  grid-column: 1 / 3;    /* from line 1 to line 3: spans two columns */
  grid-row: 1;           /* first row */
}
.banner {
  grid-column: 1 / -1;   /* -1 is the last line: full width */
}

Template areas are easier to read for whole pages; line numbers are handy for one special item inside a gallery.

Worked example: a gallery with no media queries

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
}

Read it from the inside out:

  • minmax(150px, 1fr): each column is at least 150px and at most an equal share of the space.
  • repeat(auto-fit, ...): create as many columns as fit.

On a 1,000px-wide area you get six columns; on a 350px phone you get two; at 300px, one. The tiles reflow by themselves. This single line is one of the most useful patterns in modern CSS.

Grid or Flexbox?

Use Grid whenUse Flexbox when
you control rows and columnsitems flow in one row or column
the layout comes first and content fills itthe content size comes first
page skeletons, galleries, dashboards, forms in columnsnav bars, toolbars, button groups, centring

They work together: a grid page whose header uses Flexbox for its nav is completely normal.

Inspecting a grid

In Chrome, Edge and Firefox developer tools, a small grid badge appears next to grid containers in the Elements panel. Click it to overlay the line numbers, track sizes and area names on the page. It is the quickest way to see why an item landed in the wrong cell.

Common mistakes

  • Setting display: grid on the items instead of the container.
  • A typo in an area name, so the item falls into the next free cell instead.
  • Non-rectangular template areas, which make the browser ignore the whole template.
  • Changing the visual order with grid placement so it no longer matches the HTML order, which confuses keyboard and screen reader users.
  • Fixed pixel columns everywhere (300px 300px 300px), which overflow on phones; use fr and minmax().

Quick recap

  • display: grid plus grid-template-columns (and rows) define tracks; gap spaces them.
  • fr shares the remaining space; repeat() saves typing.
  • grid-template-areas draws a page layout; items join with grid-area.
  • repeat(auto-fit, minmax(150px, 1fr)) gives a gallery that adapts with no media queries.

Try it

Open the Do tab and build a header, sidebar, main and footer page layout with template areas, plus a self-adjusting gallery.

Also in this lesson: