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.
- 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
grid items. The element itself becomes a
grid container.
.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 fr unit — 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).
Flexbox Alignment
Flexbox's alignment properties let you precisely control how items are positioned along and across the main axis — the part that trips up most learners.
When to Use Flexbox vs Grid
Flexbox and Grid both do layout — choosing between them is a question of whether your content drives the size or your template drives the size.