CSS Grid Layout Explained: Tracks, Areas and Responsive Grids
What is CSS grid?
CSS grid layout is a two-dimensional layout system that arranges content in rows and columns at the same time. You set display: grid on a parent, define its column and row tracks, and then place child items into cells or named areas. It suits page layouts, card galleries and any design where items must line up in both directions.
Grid terminology: tracks, lines, cells and areas
A grid container is the element with display: grid; its direct children are grid items. The rest of the vocabulary describes the structure the container creates.
| Term | Meaning |
|---|---|
| Track | A single column or row |
| Line | The numbered boundary between tracks, starting at 1; negative numbers count from the end |
| Cell | The space where one row and one column meet |
| Area | A rectangle of one or more cells, which can be given a name |
| Gap | The gutter between tracks, set with gap, row-gap and column-gap |
Unlike flexbox, where content pushes the layout around, grid lets the container define the structure first and then places content into it.
How grid sizes tracks: fr, repeat() and minmax()
grid-template-columns and grid-template-rows list the size of each track. You can mix fixed lengths, percentages, auto and the fr unit, which means one fraction of the space left after fixed tracks and gaps are subtracted.
.layout {
display: grid;
grid-template-columns: 240px 1fr 2fr; /* fixed, then 1:2 split of the rest */
gap: 1.5rem;
}
.twelve { grid-template-columns: repeat(12, 1fr); }
.flexible { grid-template-columns: repeat(3, minmax(200px, 1fr)); }repeat(n, size) saves you writing the same track size many times. minmax(min, max) lets a track flex between two limits, so minmax(200px, 1fr) never drops below 200px but grows to share spare space.
auto-fit versus auto-fill
Instead of a fixed count, repeat() accepts auto-fill or auto-fit, and the browser creates as many tracks as fit. The difference shows when there are fewer items than tracks. auto-fill keeps the empty tracks, so a few items stay at their minimum width. auto-fit collapses empty tracks to zero, so the existing items stretch to fill the row.
Placing items by line numbers and named areas
Items fill cells in order by default. To place one deliberately, give its start and end lines. The shorthand grid-column: 1 / -1 spans from the first line to the last, whatever the number of columns.
.feature { grid-column: 1 / 3; grid-row: 1 / 3; } /* 2 columns x 2 rows */
.banner { grid-column: 1 / -1; } /* full width */
.wide { grid-column: span 2; } /* 2 columns from wherever it lands */A page layout with grid-template-areas
Named areas let you draw the layout as text. Each string is a row, each word a column, and a dot marks an empty cell.
.page {
display: grid;
min-height: 100vh;
grid-template-columns: 220px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 1rem;
}
.page > header { grid-area: header; }
.page > aside { grid-area: sidebar; }
.page > main { grid-area: main; }
.page > footer { grid-area: footer; }
@media (max-width: 700px) {
.page {
grid-template-columns: 1fr;
grid-template-areas: "header" "main" "sidebar" "footer";
}
}Only the template changes at the breakpoint; the items keep their area names. Each area must form a rectangle, otherwise the whole declaration is ignored.
The implicit grid, a card grid without media queries, and subgrid
If there are more items than defined cells, grid creates extra tracks automatically. This is the implicit grid. Implicit rows are sized auto unless you set grid-auto-rows, and grid-auto-flow decides whether new items go into new rows or new columns.
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
grid-auto-rows: minmax(180px, auto);
gap: 1.5rem;
}This one rule gives a responsive gallery: one column on a phone, two or three on a tablet, more on a wide screen, with every card in a column the same width. Wrapping the minimum in min() stops cards overflowing on screens narrower than 250px.
Subgrid lets a nested grid reuse its parent's tracks, so content inside separate cards, such as titles, text and buttons, lines up across the row. It is supported in all current major browsers.
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid; /* title, body, button share rows with siblings */
}For subgrid rows to work, the parent grid needs rows for the card to span; pair it with grid-auto-rows: auto on the parent rather than a fixed minimum height.
Creating a grid layout step by step
- Sketch the layout and count the columns and rows it really needs.
- Add
display: gridand agapto the container. - Define columns with
grid-template-columns, usingfr,repeat()andminmax()where sizes should flex. - Leave rows implicit unless the design needs fixed rows; use
grid-auto-rowsto control their size. - Place special items with line numbers, or name areas for whole-page layouts.
- Turn on the grid overlay in your browser dev tools to see line numbers and area names while you adjust.
Recommended grid practices
- Keep the visual order close to the HTML source order; placing items far from their source position confuses keyboard and screen reader users.
- Prefer
minmax()andauto-fitover many breakpoints for repeating content. - Use named areas for page structure and line numbers for small, one-off positioning.
- Use grid for the overall frame and flexbox inside components; the two complement each other.
Practical exercise: a blog page with grid
Build a blog home page with a header, a sidebar of categories, a main area and a footer, starting from the semantic structure in the HTML guide.
- Lay out the page with
grid-template-areasand make it a single column below 700px. - Inside the main area, add nine article cards using the
auto-fitandminmax()pattern. - Make the first card span two columns and two rows on wide screens.
- Use subgrid so each card's title, excerpt and "Read more" link align across a row.
You are done when the page works from 320px upwards without horizontal scrolling and the card buttons sit on one line in each row. Page layouts like this are practised in SkillNewton's PHP foundation course alongside the server-side code that fills them.
Common mistakes
- Using
auto-fillwhen you wanted items to stretch, orauto-fitwhen you wanted them to keep a fixed width. - Drawing a non-rectangular shape in
grid-template-areas, which makes the browser ignore the whole template. - Forgetting that line numbers start at 1 and that a three-column grid has four lines.
- Setting fixed row heights that clip content when text grows or is translated.
- Rebuilding a simple one-direction toolbar with grid when flexbox would need less code.
Frequently asked questions
What does the fr unit mean in CSS grid?
One fr is one share of the free space in the grid container after fixed tracks and gaps are taken out. Two columns of 1fr 2fr split that space one third to two thirds.
What is the difference between grid-template-areas and grid-area?
grid-template-areas is set on the container and draws the named layout as rows of text. grid-area is set on an item and says which named area it occupies; it can also take line numbers as a shorthand for row and column start and end.
Can I use grid and flexbox together?
Yes. A grid item can be a flex container and a flex item can be a grid container. A common split is grid for the page frame and flexbox for components such as navigation.
Does CSS grid replace media queries?
Not entirely. Patterns such as repeat(auto-fit, minmax()) remove the need for many breakpoints, but whole-layout changes still use media or container queries, covered in our responsive design guide.