Educational guide to CSS Grid
Understand CSS Grid
Learn to think in rows, columns, tracks, and lines. Check the syntax and try alignment values in a connected preview.
Mental model
Grid organizes space in two dimensions. The container defines tracks and lines; each child occupies a cell or spans several.
The explicit grid creates the structure
grid-template-columns and grid-template-rows describe the planned tracks. Areas can give regions meaningful names.
Items occupy cells or regions
Auto-placement finds the next available cell. Lines, spans, and areas let an item occupy a specific region.
Container properties
These properties create the grid, define its tracks, and control flow, alignment, and spacing.
display
Enables Grid formatting for direct children.
- Syntax
display: grid | inline-grid;- CSS initial value
inline- Values
gridinline-grid
grid participates as a block in outer flow; inline-grid behaves as an inline-level element.
Read documentationOpens in a new tabgrid-template-columns
Defines the number and size of column tracks.
- Syntax
grid-template-columns: <track-list> | none;- CSS initial value
none- Values
repeat()minmax()<track-list>
minmax(0, 1fr) lets a flexible track shrink below the automatic minimum size of its content.
Read documentationOpens in a new tabgrid-template-rows
Defines the number and size of row tracks.
- Syntax
grid-template-rows: <track-list> | none;- CSS initial value
none- Values
repeat()minmax()<track-list>
auto rows adapt to content; fr distributes free space when the container has a definite size.
Read documentationOpens in a new tabgrid-template-areas
Describes named regions through a visual representation of the grid.
- Syntax
grid-template-areas: <string>+ | none;- CSS initial value
none- Values
<string>
Every named area must form one continuous rectangle and each string represents one row.
Read documentationOpens in a new tabgrid-auto-flow
Chooses the auto-placement axis and strategy.
- Syntax
grid-auto-flow: row | column | dense;- CSS initial value
row- Values
rowcolumnrow densecolumn dense
dense can fill earlier gaps and change visual order, but not DOM order.
Read documentationOpens in a new tabjustify-items
Aligns items within their cells on the inline axis.
- Syntax
justify-items: normal | stretch | start | center | end;- CSS initial value
legacy- Values
stretchstartcenterend
stretch only stretches an item while its inline size remains automatic.
Read documentationOpens in a new tabalign-items
Aligns items within their cells on the block axis.
- Syntax
align-items: normal | stretch | start | center | end;- CSS initial value
normal- Values
stretchstartcenterend
An item can override this value with align-self.
Read documentationOpens in a new tabjustify-content
Distributes the entire grid on the inline axis.
- Syntax
justify-content: normal | stretch | start | center | end | <content-distribution>;- CSS initial value
normal- Values
stretchstartcenterendspace-betweenspace-aroundspace-evenly
It is only visible when the tracks are smaller than the container and free space remains.
Read documentationOpens in a new tabalign-content
Distributes the entire grid on the block axis.
- Syntax
align-content: normal | stretch | start | center | end | <content-distribution>;- CSS initial value
normal- Values
stretchstartcenterendspace-betweenspace-aroundspace-evenly
It needs a definite container size and free space outside the tracks.
Read documentationOpens in a new tabgap
Adds spacing between rows and columns without child margins.
- Syntax
gap: <row-gap> <column-gap>?;- CSS initial value
normal- Values
<length><percentage>
With two values, the first is row-gap and the second is column-gap.
Read documentationOpens in a new tabItem properties
Each child can be placed with lines, spans, or areas and override its alignment inside the cell.
grid-column: 1 / span 2;grid-column and grid-row are start/end shorthands. span expresses how many tracks the item crosses.
grid-column
Places or spans an item between column lines.
- Syntax
grid-column: <grid-line> / <grid-line>;- CSS initial value
auto- Values
auto1 / span 22 / -1
Line indexes start at 1; negative indexes count back from the explicit grid end.
Read documentationOpens in a new tabgrid-row
Places or spans an item between row lines.
- Syntax
grid-row: <grid-line> / <grid-line>;- CSS initial value
auto- Values
auto1 / span 22 / span 2
span avoids manually calculating the end line when the number of tracks matters.
Read documentationOpens in a new tabgrid-area
Places an item in a named area or combines its four lines.
- Syntax
grid-area: <custom-ident> | <grid-line> / <grid-line> / <grid-line> / <grid-line>;- CSS initial value
auto- Values
auto<custom-ident><grid-line>
The shorthand order is row-start / column-start / row-end / column-end.
Read documentationOpens in a new tabjustify-self
Overrides justify-items for one item.
- Syntax
justify-self: auto | stretch | start | center | end;- CSS initial value
auto- Values
autostretchstartcenterend
auto uses the container alignment; other values create an exception.
Read documentationOpens in a new tabalign-self
Overrides align-items for one item.
- Syntax
align-self: auto | stretch | start | center | end;- CSS initial value
auto- Values
autostretchstartcenterend
Alignment moves the item inside its area, not the cell itself.
Read documentationOpens in a new tabCommon mistakes
Surprising results usually come from implicit tracks, automatic minimums, visual reordering, or an invalid area.
Undeclared rows or columns appear
- Expected result
- The layout should use only the explicitly declared rows and columns.
- Cause
- An item lands outside the explicit grid, so Grid creates implicit tracks to hold it.
- Solution
- Check placement lines and define grid-auto-rows or grid-auto-columns when those tracks are intentional.
A 1fr column causes overflow
- Expected result
- The flexible column should remain within the available container size.
- Cause
- The track automatic minimum protects content that cannot shrink.
- Solution
- Use minmax(0, 1fr), then deliberately wrap or overflow the content.
dense changes visual order
- Expected result
- The visual item order should follow the same order as the DOM.
- Cause
- The algorithm goes back to earlier holes to place later items.
- Solution
- Avoid dense when visual order communicates a sequence; DOM and keyboard navigation keep their original order.
grid-template-areas becomes entirely invalid
- Expected result
- Named areas should form a valid template and render in the grid.
- Cause
- A row has a different cell count or a name does not form a rectangle.
- Solution
- Keep the same token count in every row and ensure each name draws one continuous rectangular region.
Comparisons
Grid, Flexbox, and Grid Lanes solve different spatial relationships. Choosing the right model makes the CSS express the structure more clearly.
display: grid;compared withdisplay: flex;Two-dimensional grid or flexible flow
Grid coordinates rows and columns explicitly. Flexbox distributes content mainly on one axis and lets items negotiate space.
Try this structure in the Flexbox labdisplay: grid;compared withdisplay: grid-lanes;Aligned grid or lane-based flow
Grid aligns items across shared rows and columns. Grid Lanes keeps the columns but places each item in the available space to create masonry-like compositions.
Try this structure in the Grid Lanes lab