beginner22 min

CSS Grid Layout

Lay out rows and columns together with CSS Grid, placing and spanning items across a two-dimensional track system.

What you'll learn

  • Create a grid container with grid-template-columns and grid-template-rows
  • Place and span items across tracks using grid-column and grid-row
  • Use the fr unit and gap to build flexible, evenly spaced layouts

Prerequisites

Explanation

Flexbox is excellent at arranging items along a single row or column, but the moment you need rows and columns to line up together as one coherent system — think a page layout with a header, a sidebar, and a grid of cards — Flexbox starts to need workarounds. CSS Grid was built specifically for that two-dimensional case.

Creating a Grid

Setting display: grid; on a container turns it into a grid, but by itself that grid has no defined columns yet. You describe the columns with grid-template-columns, and the rows with grid-template-rows. Each value in the list defines one track:

grid-template-columns: 1fr 1fr 1fr;

creates three column tracks. The fr unit means "a fraction of the remaining free space" — three equal 1fr tracks split available width evenly, and you can mix them, e.g. 1fr 2fr gives the second column twice the width of the first. Repeating the same track over and over is common enough that CSS provides a shortcut: repeat(3, 1fr) is identical to writing 1fr 1fr 1fr.

Gap

gap (previously written as grid-gap) adds consistent spacing between both rows and columns at once, without needing margins on individual items — the same property Flexbox uses, working the same way.

Placing and Spanning Items

By default, grid items fill in tracks automatically, left to right, wrapping to the next row when a row fills up — much like text wrapping. But you can also explicitly place or stretch an item using grid line numbers. Grid lines are numbered starting at 1, counting the boundaries between (and around) your tracks — a three-column grid has four column lines: 1, 2, 3, and 4. grid-column: 1 / 3 stretches an item from line 1 to line 3, spanning the first two column tracks. The special value -1 always refers to the very last line, so grid-column: 1 / -1 spans an item across every column, regardless of how many there are — a common pattern for a full-width header sitting above a multi-column layout beneath it.

Grid vs. Flexbox

The core distinction to keep in your head: Grid is two-dimensional — you define both rows and columns together, and content is placed into that shared structure. Flexbox is one-dimensional — it only ever arranges items along a single line, wrapping onto new lines as an overflow behavior rather than a deliberate row-and-column plan. Neither replaces the other; a real page commonly uses Grid for its overall page layout, and Flexbox for arranging items within one of those grid areas, like a row of buttons inside a card.

Grid can do a great deal more — named grid areas, implicit tracks, minmax() for flexible sizing — but display: grid, grid-template-columns with fr units, gap, and grid-column/grid-row spans already cover a large share of real layout work.

1234grid-template-columns: repeat(3, 1fr)

Grid tracks and lines

A grid container is divided by numbered grid lines into column tracks and row tracks — a three-column grid has four vertical grid lines, numbered 1 through 4. grid-template-columns: repeat(3, 1fr) creates three equal-width column tracks between those lines. An item can span multiple tracks using line numbers, e.g. grid-column: 1 / -1 stretches it from the first line to the last line, covering the full width regardless of how many columns exist.

Example

A page layout using CSS Grid: a full-width header spanning three equal columns of cards beneath it.

<!doctype html>
<html>
  <head>
    <style>
      .layout {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-template-rows: auto 1fr;
        gap: 12px;
      }
      .header {
        grid-column: 1 / -1;
        background: #333;
        color: white;
        padding: 10px;
      }
      .card {
        background: #eee;
        padding: 10px;
      }
    </style>
  </head>
  <body>
    <div class="layout">
      <div class="header">Site header spans all three columns</div>
      <div class="card">Card 1</div>
      <div class="card">Card 2</div>
      <div class="card">Card 3</div>
    </div>
  </body>
</html>

Try it yourself

Change repeat(3, 1fr) to repeat(2, 1fr) and press Run to see the layout reflow into two columns.

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Guided exercise

Guided exercise

Turn #grid into a grid container with three equal-width columns: add display: grid; and grid-template-columns: repeat(3, 1fr);

Checks: #grid has display: grid · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Independent exercise

Independent exercise

Make #layout a grid with grid-template-columns: repeat(3, 1fr);. Make .header span the full width using grid-column: 1 / -1;. The three .card elements should sit together in the row below the header.

Checks: #layout is a grid container · .header spans the full width · The header sits above the cards · plus 1 hidden check

Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.

Loading editor…

Stuck? Get a hint.

Common mistakes

  • Confusing Grid's two-dimensional row-and-column placement with Flexbox's one-dimensional row-or-column layout — reach for Grid when rows and columns need to line up together.
  • Forgetting that grid line numbers start at 1, not 0, and that -1 refers to the last line, not the last track.
  • Writing grid-template-columns: 1fr 1fr 1fr and expecting gap to be part of that list — gap is a separate property, not a track value.
  • Applying grid-column or grid-row to the container instead of to the child item that should span or move within it.

Knowledge check

Knowledge check

1. What does grid-template-columns: repeat(3, 1fr); create?
2. What does grid-column: 1 / -1 do to an item?
3. Which property turns a container into a grid?
4. What is the main practical difference between Grid and Flexbox?

Takeaway

CSS Grid lets you lay out rows and columns together as one system, instead of faking a grid with nested flex containers.

Summary

display: grid combined with grid-template-columns (often using the fr unit or repeat()) defines a two-dimensional track system. Items can span multiple tracks using grid-column and grid-row line numbers, with gap handling spacing — making Grid the right tool whenever rows and columns need to work together, unlike the single-axis layouts Flexbox handles.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.