CSS Grid — The Basics
Build a real mental model of CSS Grid: turning a container into a grid, defining column and row tracks, the flexible fr unit, the lines and cells that tracks create, spacing with gap, and how items are placed.
Introduction
CSS Grid is a two-dimensional layout system: it lays out elements in rows and columns at the same time, which is what sets it apart from older one-dimensional tools. Where a float or an inline row only reasons about a single axis, a grid reasons about both axes together, so the horizontal and vertical structure of a layout is described in one place.
Why does a second layout model exist alongside Flexbox? Because page structure and content flow solve different problems. Reach for Flexbox when you have a *line* of items that should distribute along one axis; reach for Grid when you have a *structure* — a header, a sidebar, a main area, a footer — whose rows and columns you want to define up front. Most real interfaces use both: a grid for the page skeleton, flex for the pieces inside each cell.
One idea makes the whole model predictable, and this guide is built around it. You first turn one element into a grid container, then you describe its tracks — the columns and rows — and the browser slots the children into the cells those tracks create. Hold that frame and everything else on this page is detail: sizing tracks, spacing them, and nudging items around.
Lessons
1. Turning a container into a grid
Everything starts with the container. Setting display: grid on an element promotes it to a grid container, and every *direct child* becomes a grid item that the grid will position. Nothing visible changes yet — with no tracks defined, the browser gives you a single implicit column and stacks the children in rows. The declaration is the switch; the track definitions that follow are what give the layout its shape.
.container {
display: grid; /* this element is now a grid container */
}
2. Defining columns and rows
You describe the grid's structure with grid-template-columns and grid-template-rows. Each value is a list of track sizes, and the number of values is the number of tracks. grid-template-columns: 200px 1fr means "a fixed 200-pixel first column, then a second column that takes the rest"; a matching grid-template-rows does the same vertically. This is the heart of the model — you are declaring the skeleton, and items flow into it left to right, top to bottom.
.container {
display: grid;
grid-template-columns: 200px 1fr; /* two columns */
grid-template-rows: auto auto; /* two rows */
}
3. The fr unit and flexible tracks
The fr unit is Grid's own length: one fr is one *fraction* of the free space left after fixed sizes are subtracted. grid-template-columns: repeat(3, 1fr) makes three equal columns; 2fr 1fr makes the first twice as wide as the second. Because fr distributes remaining space rather than a fixed amount, a grid built from fractional tracks resizes fluidly with its container — no percentages, no manual arithmetic. This is why fr is the unit you reach for first.
.container {
display: grid;
grid-template-columns: 2fr 1fr; /* first column twice as wide */
}
4. Tracks, lines and cells
Three terms describe the grid's geometry, and keeping them straight is most of the mental model. A track is a single column or row — the space between two adjacent grid lines. The lines are the numbered dividers *between* tracks: a grid with three columns has four vertical lines, numbered 1 through 4. Where a column track crosses a row track you get a cell, the smallest unit an item can occupy. Items are placed by referring to these line numbers, which is why the counting starts to matter as layouts grow.
- Track — one column or one row; its size is what
grid-template-columns/grid-template-rowssets. - Line — a numbered divider between tracks; N tracks produce N+1 lines.
- Cell — the intersection of one column track and one row track; the atomic placement unit.
5. Spacing tracks with gap
To put space *between* tracks without touching the items themselves, use the gap property. gap: 1rem adds a one-rem gutter between every row and every column; the two-value form gap: 12px 24px sets the row gap and the column gap separately. The important nuance is that gap only adds space *between* tracks, never around the outer edge of the grid — outer spacing is still the container's own padding. Because it is applied on the container, one declaration spaces the whole grid consistently.
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem; /* gutter between tracks */
}
6. Placing items
By default items auto-place into cells in order, one per cell, filling each row before moving to the next. When you want an item to break that flow — to span two columns, or to start at a specific line — you set grid-column and grid-row on the *item* using the line numbers from lesson four. grid-column: 1 / 3 means "start at line 1, end at line 3," so the item spans the first two columns. Placement is a deep topic on its own; for now the takeaway is that the container defines the grid and individual items can opt out of auto-placement when they need to.
That is the whole model. You turn a container into a grid with display: grid; you define column and row tracks with grid-template-columns and grid-template-rows, sizing flexible ones with the fr unit; those tracks create lines and cells; you space them with gap; and items auto-place into the cells unless you position them by line. Every advanced Grid feature — named areas, repeat(), minmax(), auto-fit — rests on that frame.
Practice
Check your model before you run anything: given grid-template-columns: repeat(3, 1fr) and six children, how many rows appear? (Answer: two — three cells per row, so the fourth child wraps onto a new row that the grid creates automatically.)
Now experiment for real. This grid uses three flexible fr columns and a gap; change the track list or the gap and watch the numbered cells rearrange:
Next steps
You have the mental model — now put it to work. Follow how to create a grid layout for a step-by-step build, browse the runnable CSS Grid examples for copy-paste patterns, or read the references for the grid-template-columns property and the gap property. If you are laying out a single row of items instead, compare with CSS Flexbox. Every snippet runs in the editor.
Frequently asked questions
What is the difference between CSS Grid and Flexbox?
What does the fr unit mean in CSS Grid?
repeat(2, 1fr) splits the remaining space into two equal columns; 2fr 1fr makes the first twice as wide as the second.How do I add space between grid items?
gap property on the grid container. gap: 1rem adds a gutter between every row and column; the two-value form gap: 12px 24px sets the row gap and column gap separately. It only spaces tracks, never the outer edge.