CSS Grid Mastery: From Basics to Advanced Layouts
Master CSS Grid from fundamentals to advanced patterns. Covers grid-template, fr units, repeat(), auto-fit/auto-fill, minmax(), grid-template-areas, implicit grids, dense packing, alignment, overlapping items, and real-world layouts like dashboards and bento grids.
- 1. CSS Flexbox Mastery: The Complete Visual Guide to Flexible Layouts
- 2. CSS Grid Mastery: From Basics to Advanced Layouts
- 3. CSS Custom Properties (Variables) Mastery: Dynamic Theming & Beyond
- 4. CSS Animations & Transitions Mastery: From Hover Effects to Keyframe Sequences
- 5. CSS Selectors Deep Dive: From Basic to :has() & :is()
- 6. CSS Box Model Mastery: Content, Padding, Border & Margin Explained
- 7. CSS Responsive Design Mastery: Mobile-First, clamp(), & Container Queries
- 8. CSS Specificity & Cascade Mastery: How Browsers Resolve Conflicts
- 9. CSS Modern Layout Techniques: Scroll Snap, Subgrid, Logical Properties & More
- 10. CSS Pseudo-Elements Mastery: ::before, ::after, Counters & Decorative Techniques
CSS Grid is the most powerful layout system in CSS. While Flexbox handles one dimension (row or column), Grid handles both dimensions at the same time — rows AND columns. It lets you create complex, responsive layouts that would have required nested div hacks and frameworks in the past.
If Flexbox is a ruler (measuring one direction), CSS Grid is a graph paper where you control both the horizontal and vertical axes simultaneously.
In this guide, we'll cover everything from basic grid creation to advanced techniques like grid-template-areas, auto-fit, and subgrid.
1. Creating a Grid: The Two Players
Just like Flexbox, Grid has two roles:
- Grid Container — The parent element with
display: grid. - Grid Items — The direct children of the container.
.container {
display: grid;
}
The moment you add display: grid, the children become grid items. But unlike Flexbox, nothing visually changes yet — you need to define the rows and columns.
2. Defining Columns and Rows
grid-template-columns
This property defines how many columns your grid has and how wide each one is.
.container {
display: grid;
grid-template-columns: 200px 200px 200px; /* 3 equal columns */
}
grid-template-rows
This property defines the height of each row.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 100px 200px; /* Row 1 = 100px, Row 2 = 200px */
}
3. The fr Unit: Fractional Space
The fr (fraction) unit is unique to CSS Grid. It represents a fraction of the available space in the grid container.
.container {
grid-template-columns: 1fr 2fr 1fr;
/* Total = 4fr. Column 1 = 25%, Column 2 = 50%, Column 3 = 25% */
}
fr vs Percentages
| Feature | fr | % |
|---|---|---|
| Considers gap? | ✅ Yes (subtracts gap first) | ❌ No (can cause overflow) |
| Relative to | Available space after gaps | Container total width |
| Best for | Grid layouts | Fixed proportions |
Mixing Units
You can mix fr with fixed units. Fixed units get their space first, then fr divides the remainder:
.container {
grid-template-columns: 250px 1fr 1fr;
/* Sidebar is fixed 250px. Two main columns share the rest equally. */
}
4. The repeat() Function
Tired of writing 1fr 1fr 1fr 1fr? Use repeat():
.container {
grid-template-columns: repeat(4, 1fr); /* Same as: 1fr 1fr 1fr 1fr */
}
You can combine repeat() with other values:
.container {
grid-template-columns: 200px repeat(3, 1fr); /* Fixed + 3 flexible */
}
5. The gap Property
Just like in Flexbox, gap adds spacing between grid items — but not on the outer edges.
.container {
display: grid;
gap: 1rem; /* Same gap in both directions */
/* OR */
row-gap: 1rem; /* Vertical gap between rows */
column-gap: 2rem; /* Horizontal gap between columns */
}
6. Placing Items: Grid Lines
Grid creates invisible lines you can use to place items precisely. A 3-column grid has 4 column lines (numbered 1–4).
grid-column and grid-row
Use these on grid items to control their position:
.item {
grid-column: 1 / 3; /* Start at line 1, end at line 3 (spans 2 columns) */
grid-row: 1 / 2; /* Start at line 1, end at line 2 (1 row) */
}
The span Keyword
Instead of specifying end lines, you can say "span X cells":
.item {
grid-column: span 2; /* Span 2 columns from wherever I am */
}
Pro Tip:
grid-column: 1 / -1means "from the first line to the last line" — a full-width span regardless of how many columns exist. The-1refers to the very last grid line.
7. grid-template-areas: Visual Layout
This is one of Grid's most powerful and beginner-friendly features. You can name areas and "draw" your layout using ASCII-art-style strings:
.container {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 60px 1fr 50px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
Empty Cells
Use a period (.) to leave a cell empty:
grid-template-areas:
"header header"
". content"
"footer footer";
8. auto-fit and auto-fill: Responsive Without Media Queries
These two keywords inside repeat() create responsive grids that automatically adjust the number of columns based on available space.
auto-fill
Creates as many columns as can fit, even if they're empty:
.container {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
auto-fit
Same as auto-fill, but collapses empty columns so existing items stretch to fill the space:
.container {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
The Difference Visualized
Rule of Thumb: Use
auto-fitin 90% of cases. It's what you want when items should fill the available space. Useauto-fillwhen you need to maintain empty column slots (e.g., for drag-and-drop placeholders).
9. minmax(): Setting Size Boundaries
The minmax() function defines a size range for grid tracks:
.container {
grid-template-columns: minmax(200px, 1fr) 2fr;
/* First column: min 200px, max 1fr */
}
| Pattern | Meaning |
|---|---|
minmax(200px, 1fr) | At least 200px, grows with available space |
minmax(0, 1fr) | Can shrink to 0, grows freely |
minmax(auto, 300px) | Content-sized minimum, max 300px |
The magic of responsive grids lives in this combination:
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
This means: "Create as many columns as fit, each at least 250px wide, and stretch them equally to fill remaining space."
10. Implicit vs Explicit Grid
The grid you define with grid-template-columns and grid-template-rows is the explicit grid. But what happens when you have more items than cells?
Grid automatically creates implicit rows (or columns) to accommodate the extra items.
Controlling Implicit Tracks
.container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* Explicit: 3 columns */
grid-template-rows: 100px; /* Explicit: 1 row */
grid-auto-rows: 80px; /* Implicit rows are 80px */
}
| Property | Controls |
|---|---|
grid-auto-rows | Height of auto-created rows |
grid-auto-columns | Width of auto-created columns |
grid-auto-flow | Direction items are placed (row, column, dense) |
11. grid-auto-flow: Dense Packing
When items are placed, gaps can appear in the grid. grid-auto-flow: dense tells the browser to go back and fill those gaps with smaller items.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-flow: dense; /* Fill gaps with smaller items */
}
Warning:
densecan reorder items visually, which may confuse screen readers and keyboard navigators. Use it for non-content layouts like image galleries, not for sequential content.
12. Alignment in Grid
Grid supports the same alignment properties as Flexbox, but in two dimensions.
Container Properties
| Property | Axis | What it Aligns |
|---|---|---|
justify-items | Inline (horizontal) | All items inside their cells |
align-items | Block (vertical) | All items inside their cells |
justify-content | Inline (horizontal) | The entire grid within the container |
align-content | Block (vertical) | The entire grid within the container |
Item Properties
| Property | What it Does |
|---|---|
justify-self | Overrides justify-items for one item |
align-self | Overrides align-items for one item |
The place-* Shorthands
place-items: center; /* align-items + justify-items */
place-content: center; /* align-content + justify-content */
place-self: center; /* align-self + justify-self */
13. Named Lines
You can name grid lines and refer to them by name, making your code more readable:
.container {
display: grid;
grid-template-columns:
[sidebar-start] 250px
[sidebar-end content-start] 1fr
[content-end];
}
.sidebar {
grid-column: sidebar-start / sidebar-end;
}
This is especially useful in large layouts where remembering line numbers becomes difficult.
14. Overlapping Items
Unlike Flexbox, Grid allows items to overlap by placing them on the same grid cells. Control stacking with z-index:
.item-a {
grid-column: 1 / 3;
grid-row: 1 / 2;
z-index: 1;
}
.item-b {
grid-column: 2 / 4;
grid-row: 1 / 2;
z-index: 2; /* On top */
}
15. Real-World Grid Patterns
Pattern 1: Dashboard Layout
.dashboard {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 60px 1fr;
grid-template-areas:
"nav header"
"nav main";
height: 100vh;
}
Pattern 2: Responsive Card Grid
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
}
Pattern 3: Bento Grid
A trendy layout where different items span different numbers of rows and columns:
.bento {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 150px;
gap: 1rem;
}
.bento-large {
grid-column: span 2;
grid-row: span 2;
}
16. Grid vs Flexbox: Quick Decision Guide
| Scenario | Use | Why |
|---|---|---|
| Centering a single element | Flexbox or Grid | Both work with place-items: center |
| Navigation bar | Flexbox | One-dimensional, content-driven |
| Card grid (equal columns) | Grid | Two-dimensional, layout-driven |
| Sidebar + main content | Grid | Clear column/row structure |
| Tags/chips in a row | Flexbox | One-dimensional, wrapping |
| Dashboard with named areas | Grid | grid-template-areas is unmatched |
| Overlapping elements | Grid | Flexbox can't overlap items |
17. Common Mistakes & Gotchas
Mistake 1: 100% vs 1fr with Gaps
If you use grid-template-columns: 50% 50%, the columns total 100% — but the gap adds extra width, causing overflow. Use 1fr 1fr instead.
Mistake 2: Forgetting min-width on Grid Items
Just like Flexbox, grid items have min-width: auto. Long text content can overflow. Fix with min-width: 0 or overflow: hidden.
Mistake 3: auto-fit minmax with Fixed Max
/* ❌ Items won't stretch beyond 300px */
grid-template-columns: repeat(auto-fit, minmax(200px, 300px));
/* ✅ Items stretch to fill space */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
Mistake 4: Using Grid for Everything
Grid is powerful, but not every layout needs it. A simple row of items? Use Flexbox. Grid shines when you need two-dimensional control.
Conclusion
CSS Grid gives you architect-level control over web layouts:
grid-template-columns/rows— Define your grid structurefr— Fractional, gap-aware sizingrepeat(auto-fit, minmax())— Responsive without media queriesgrid-template-areas— Visual, named layout regionsgrid-column/row: span— Items spanning multiple cellsgrid-auto-flow: dense— Fill gaps automaticallyplace-items/content— Alignment in both dimensions
The combination of Flexbox for components and Grid for page layouts is the modern CSS layout toolkit. Master both, and you'll never need a CSS framework for layout again!
🧠 Test Your Knowledge
Now that you've learned the concepts, let's see if you can apply them! Take this quick quiz to test your understanding.