Code of the Day
IntermediateLayout Systems

CSS Grid

CSS Grid is a two-dimensional layout model — it controls both rows and columns simultaneously, making complex page layouts composable without nested hacks.

Web FoundationsIntermediate10 min read
Recommended first
By the end of this lesson you will be able to:
  • Define a grid with explicit column tracks using grid-template-columns
  • Use the fr unit to create proportional column widths
  • Place grid items explicitly with grid-column and grid-row span notation
  • Name template areas and assign items to them with grid-template-areas
  • Build a responsive grid with repeat and minmax without writing a media query

Flexbox is great at arranging items in a line. The moment you need rows and columns to align with each other — a page layout with a sidebar, or a card grid where items in different rows share column boundaries — Flexbox starts to strain. CSS Grid was built for exactly that.

Defining a grid container

Add display: grid to any element and its direct children become . The element itself becomes a .

.layout {
  display: grid;
}

Without column definitions, items still stack vertically — Grid's default is one implicit column that fills the container. Grids become useful the moment you define tracks.

grid-template-columns and the fr unit

grid-template-columns defines how many columns the grid has and how wide each one is. Values are space-separated:

.layout {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;
}

This creates three columns: the first is exactly 200 pixels, and the remaining two share the leftover space equally. The — short for "fraction" — means "one part of the available space after fixed-size tracks are satisfied."

grid-template-columns: 1fr 2fr;  /* two columns, second is twice as wide */
grid-template-columns: 1fr 1fr 1fr;  /* three equal columns */

grid-template-rows

Rows work the same way. In most cases you can leave rows implicit — the browser creates new rows automatically as items overflow the defined columns. Define rows explicitly only when you need fixed or minimum heights:

.layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto 1fr auto;  /* header, stretchy middle, footer */
}

gap

The same gap property from Flexbox applies here, but now both row and column gaps are meaningful:

.layout {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 16px;          /* same gap in both directions */
  /* or: gap: 24px 16px;  row-gap column-gap */
}

Placing items explicitly

By default, grid items flow into cells in order — left to right, top to bottom. To place an item at a specific location or to span multiple tracks, use grid-column and grid-row:

.featured {
  grid-column: 1 / 3;  /* from column line 1 to column line 3 (spans 2 columns) */
  grid-row: 1 / 2;     /* first row only */
}

Grid lines are numbered from 1 (not 0). A three-column grid has four column lines. The shorthand span N is often more readable than explicit line numbers:

.wide-card {
  grid-column: span 2;  /* start wherever auto-placement puts it, span 2 columns */
}

Named template areas

For page-level layouts, grid-template-areas lets you draw the structure in CSS and then assign items to areas by name — which is dramatically more readable than line numbers:

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
}

.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }

The quoted strings in grid-template-areas must form a rectangle. Each cell that an area spans is written as a repeated name. A dot (.) represents an empty cell.

Named template areas are the single biggest readability win CSS Grid offers. If you are doing a page-level layout and are still thinking in line numbers, switch to named areas — future you will thank present you.

repeat() and minmax(): responsive grids without media queries

Two functions unlock the full power of Grid for adaptive layouts:

  • repeat(N, size) — shorthand for repeating a track definition N times.
  • minmax(min, max) — sets a minimum and maximum size for a track.

Combine them with the auto-fit keyword and you get a grid that adds and removes columns automatically based on available space:

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

Read this as: "create as many columns as fit, each at least 240px wide, sharing any leftover space equally." At a wide viewport you might get four columns; at a narrow viewport, two; on mobile, one — all without a single media query.

auto-fill is the close sibling of auto-fit. The difference: auto-fit collapses empty tracks (so items stretch to fill the container), while auto-fill keeps them (leaving empty columns at the end). Use auto-fit for most card grids.

repeat(auto-fit, minmax(240px, 1fr)) is powerful but has one edge case: if the container is narrower than 240px, the minimum constraint will cause overflow. Use minmax(min(240px, 100%), 1fr) — the inner min() ensures the track never requests more than 100% of the container width even on very small screens.

A page-level example

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 64px 1fr 48px;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  min-height: 100vh;
  gap: 0;
}

.page-header  { grid-area: header;  background: #1a1a2e; }
.page-sidebar { grid-area: sidebar; background: #f5f5f5; }
.page-main    { grid-area: main;    padding: 24px; }
.page-footer  { grid-area: footer;  background: #333; }

Notice that the header and footer span both columns because both cells in those rows share the same area name. The sidebar and main content share the middle row. This is the page structure you will build in the lab at the end of this module.

Where to go next

You can build one-dimensional layouts with Flexbox and two-dimensional ones with Grid. Next: When to Use Flexbox vs Grid — a practical decision framework for choosing between them (and for combining them).

Finished reading? Mark it complete to track your progress.

On this page