CSS Grid Demystified
Master CSS Grid from zero to expert — grid basics, template columns & rows, gap, named areas, item placement & spanning, alignment, auto-flow, responsive patterns, real-world layouts, and a full interactive playground.
The Big Picture — What is CSS Grid?
CSS Grid is the most powerful layout system in CSS. Unlike Flexbox which works in one dimension (row OR column), Grid works in two dimensions simultaneously — giving you precise control over both rows and columns at the same time. It lets you define a grid structure and place items into it with pixel-perfect precision.
Grid vs Flexbox — When to Use Which?
Grid and Flexbox are complementary. Use Grid for 2D layouts, Flexbox for 1D alignment.
📐 CSS Grid — 2D
Controls rows AND columns
↔️ Flexbox — 1D
Controls ONE axis at a time
| Feature | CSS Grid | Flexbox |
|---|---|---|
| Dimensions | 2D — rows AND columns simultaneously | 1D — either row OR column |
| Layout approach | Layout-first (define grid, place items) | Content-first (items determine layout) |
| Alignment | Both axes independently | Main axis + cross axis |
| Overlap | Items can overlap (z-index) | Items cannot overlap |
| Gap | Native gap property | Native gap property (newer) |
| Best for | Page layouts, dashboards, card grids | Navbars, toolbars, inline content |
Grid Terminology
Click each term to see it highlighted on the grid.
The element with display: grid. It establishes the grid formatting context for its children.
display: grid;Visual Grid Anatomy — 3×2 Grid
🔑 Key Takeaway: CSS Grid is a 2D layout system. The container defines the grid structure (tracks, lines, areas), and items are placed into cells either automatically or with explicit coordinates.
grid-template-columns
The grid-template-columnsproperty defines how many columns your grid has and how wide each one is. This is where you'll spend most of your time — mastering the fr unit, repeat(), minmax(), and the difference between auto-fill and auto-fit.
Grid Sizing Units
The building blocks for defining column and row sizes.
Distributes remaining space. 1fr 2fr = first gets 1/3, second gets 2/3.
Fixed size. Doesn't grow or shrink. Use for sidebars or fixed columns.
Percentage of the container width. Doesn't account for gaps.
Sizes to content. Shrinks to fit, grows if space available.
Sets a min and max size. minmax(100px, 1fr) = at least 100px, up to 1fr.
Like auto but capped at the given size. fit-content(200px) won't exceed 200px.
grid-template-columns — Interactive
Select a preset or type your own column definition.
Three columns of equal width. Each gets 1 fraction of available space.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 8px;
}auto-fill vs auto-fit — The Key Difference
auto-fill: keeps empty tracks
Empty columns exist but items don't stretch into them
auto-fit: collapses empty tracks
Empty columns collapse — items stretch to fill the row
🔑 Key Takeaway: grid-template-columns defines your column structure. Use fr for flexible proportions, px for fixed sizes, minmax() for responsive ranges, and auto-fill/auto-fit for dynamic column counts that adapt to container width.
grid-template-rows
Rows work just like columns but on the vertical axis. The key difference: fr units for rows only work when the container has an explicit height. Without it, rows default to auto (content-sized). Understanding explicit vs implicit rows is critical.
grid-template-rows — Interactive
Rows work the same as columns — but vertically. The key difference: fr units for rows require the container to have an explicit height.
Rows size to their content. Most common default behavior.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto auto auto;
gap: 8px;
height: 400px;
}Explicit vs Implicit Rows
Explicit Rows
Defined by grid-template-rows. You control their exact size.
Implicit Rows
Created automatically when items overflow the explicit grid. Sized by grid-auto-rows (default: auto).
/* Size implicit (overflow) rows */
.container {
grid-template-rows: 100px 100px; /* 2 explicit rows */
grid-auto-rows: 60px; /* all extra rows = 60px */
}🔑 Key Takeaway: grid-template-rows defines explicit row heights. Use auto for content-sized rows, px for fixed heights, and fr for proportional distribution (requires explicit container height). Use grid-auto-rows to size implicit overflow rows.
gap — Spacing Between Tracks
The gap property (formerly grid-gap) adds gutters between grid tracks. Unlike margins, gap only applies between items — never on the outer edges. You can set row-gap and column-gap independently for asymmetric spacing.
gap, row-gap, column-gap
Gap adds spacing between grid tracks (not around the outer edges). It replaced the older grid-gap property.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}gap vs margin — Why Gap Is Better
✅ gap
- • Only between items (no outer spacing)
- • Works with grid AND flexbox
- • No collapsing margin issues
- • One property controls all gutters
❌ margin
- • Adds spacing on ALL sides (extra on edges)
- • Need negative margin hacks to fix
- • Margins collapse between items
- • Each item needs its own margin
🔑 Key Takeaway: The gap property adds gutters between grid tracks without affecting the outer edges. Use the shorthand gap: row col or set row-gap and column-gap independently. Always prefer gap over margins for grid spacing.
grid-template-areas — Named Layouts
Grid areas let you define layouts visually in your CSS. Each string represents a row, each word a column. Name your regions (header, sidebar, main, footer) and assign items to them with grid-area. It's the most readable way to create complex page layouts.
grid-template-areas — Named Layouts
Define layouts visually using named areas — the most readable way to create complex grids. Each string is a row, each word is a column.
Area Map (each string = one row)
grid-template-areas: "header header header" "nav main aside" "footer footer footer"
.container {
display: grid;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
grid-template-rows: auto 1fr auto;
grid-template-columns: 200px 1fr 200px;
gap: 8px;
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }💡 Empty Cells: Use a dot (.)
Use . to leave a cell empty in your area template:
grid-template-areas: "header header header" ". main ." "footer footer footer";
🔑 Key Takeaway: grid-template-areas lets you design layouts visually in your CSS. Name each region, then assign items with grid-area. It's the most readable way to create complex page layouts and makes responsive redesigns trivial.
Item Placement & Spanning
By default, grid items fill cells left-to-right, top-to-bottom. But you can place any item anywhere using grid-column and grid-row with line numbers or the span keyword. Negative line numbers count from the end — grid-column: 1 / -1 spans the entire row.
Item Placement & Spanning
Control exactly where items go using grid-column, grid-row, span, and line numbers.
Place items using grid line numbers. A 3-column grid has lines 1, 2, 3, 4. Negative numbers count from the end.
/* Item A */ .item-A { grid-column: 1 / 3; grid-row: 1; } /* Item B */ .item-B { grid-column: 3; grid-row: 1 / 3; } /* Item C */ .item-C { grid-column: 1; grid-row: 2; } /* Item D */ .item-D { grid-column: 2; grid-row: 2; } /* Item E */ .item-E { grid-column: 1 / -1; grid-row: 3; }
Click any item above to highlight it
Placement Property Cheat Sheet
grid-column: 1 / 3Start at column line 1, end at line 3 (spans 2 columns)grid-column: span 2Span 2 columns from current positiongrid-column: 1 / -1Span the entire row (line 1 to last line)grid-row: 2 / span 3Start at row line 2, span 3 rowsgrid-area: 2 / 1 / 4 / 3Shorthand: row-start / col-start / row-end / col-end🔑 Key Takeaway: Grid items can be placed anywhere on the grid using line numbers (grid-column: 1 / 3), span counts (grid-column: span 2), or named areas. Negative line numbers count from the end — grid-column: 1 / -1 spans the entire row.
Alignment & Justification
Grid has 6 alignment properties: justify-items and align-items position items within their cells, justify-content and align-content position the grid within its container, and justify-self / align-self override alignment for individual items.
Grid Alignment — 6 Properties
Grid has 6 alignment properties: 2 for items-in-cells, 2 for grid-in-container, 2 for individual overrides.
justify-itemsalign-itemsjustify-contentalign-contentjustify-selfalign-selfInteractive Alignment Demo
justify-items (horizontal)
align-items (vertical)
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
justify-items: stretch;
align-items: stretch;
}Shorthand Properties
place-items: center→align-items: center; justify-items: center;place-content: center→align-content: center; justify-content: center;place-self: end center→align-self: end; justify-self: center;🔑 Key Takeaway: justify-* controls the inline (horizontal) axis, align-* controls the block (vertical) axis. *-items positions items within their cells, *-content positions the entire grid within its container. place-* is the shorthand for both.
grid-auto-flow — Automatic Placement
When you don't explicitly position items, the auto-placement algorithm decides where they go. grid-auto-flowcontrols whether items fill by row or by column, and whether the "dense" packing algorithm should backfill gaps left by larger items.
grid-auto-flow — Automatic Placement
Controls how the auto-placement algorithm fills items into the grid when you don't explicitly position them.
Items fill each row left-to-right, then wrap to the next row. Most common.
Notice how "dense" fills the gap left by wide/tall items, while non-dense leaves holes.
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 60px;
grid-auto-flow: row;
gap: 6px;
}
.item-a { grid-column: span 2; }
.item-c { grid-row: span 2; }
.item-e { grid-column: span 2; }The Implicit Grid
When items overflow the explicit grid (defined by grid-template-*), the browser creates implicit tracks. Control their size with:
grid-auto-rows: 60pxAll implicit rows are 60px tallgrid-auto-rows: minmax(60px, auto)At least 60px, grows with contentgrid-auto-columns: 200pxAll implicit columns are 200px wide🔑 Key Takeaway: grid-auto-flow controls how items are placed automatically. "row" fills left-to-right, "column" fills top-to-bottom. Add "dense" to backfill gaps — useful for card grids and masonry layouts. Use grid-auto-rows/columns to size implicit tracks.
Responsive Grid Patterns
CSS Grid can create fully responsive layouts without a single media query. The magic formula: repeat(auto-fit, minmax(200px, 1fr))— this creates as many columns as fit, each at least 200px wide, stretching to fill available space. It's one line of CSS that replaces dozens of breakpoint rules.
Responsive Grid Patterns
CSS Grid can create responsive layouts without a single media query. The key: auto-fit/auto-fill + minmax().
The gold standard for responsive grids. No media queries needed. Items are at least 150px wide and stretch to fill remaining space. Columns adjust automatically to container width.
↔ Resize your browser window to see the grid adapt
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
Common Breakpoint Strategy
grid-template-columns: 1fr;grid-template-columns: repeat(2, 1fr);grid-template-columns: repeat(3, 1fr);grid-template-columns: repeat(4, 1fr);🔑 Key Takeaway: repeat(auto-fit, minmax(200px, 1fr)) is the single most useful CSS Grid pattern. It creates a fully responsive grid that adapts to any container width — no media queries, no JavaScript, just one line of CSS.
Real-World Layouts
These are the 5 layout patterns you'll use most often: the Holy Grail (header + sidebar + content + sidebar + footer), responsive card grids, dashboard layouts, magazine-style featured content, and the simplest centering technique in all of CSS.
Real-World Grid Layouts
Common layout patterns you'll use daily. Click each to see the live preview and CSS.
The classic web layout: header, footer, main content flanked by two sidebars. Grid makes this trivial with named areas.
.layout {
display: grid;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
gap: 8px;
}🔑 Key Takeaway: CSS Grid excels at page-level layouts. The Holy Grail layout is 6 lines of CSS. Card grids are 3 lines. Perfect centering is 2 lines. Master these 5 patterns and you can build any layout.
Grid Playground
Experiment freely with every grid property. Adjust columns, rows, gap, alignment, and item count — or type custom template values. The generated CSS updates in real-time and is ready to copy into your project.
Full Grid Playground
Experiment freely — adjust every grid property and see the result instantly.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, minmax(60px, 1fr));
gap: 10px;
justify-items: stretch;
align-items: stretch;
}🔑 Key Takeaway: CSS Grid gives you complete 2D control. Define columns and rows, set gap spacing, align items within cells, and the browser handles all the math. Copy the generated CSS into your project and customize from there.