CSS Grid
Grid is a two-dimensional layout system. Define rows and columns, then place items into the resulting cells. Unlike flexbox, which flows in one direction, grid controls both axes simultaneously.
Grid solves the layout problems that required complex float and positioning hacks: magazine layouts, asymmetric designs, overlapping content.
The Grid Container
Apply display: grid to a parent element. Its direct children become grid items.
.layout {
display: grid;
}Without further properties, items stack vertically in a single column. You need to define the grid structure.
Grid Template Columns and Rows
Define column widths with grid-template-columns and row heights with grid-template-rows.
.layout {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}This creates a three-column layout: fixed sidebars with a flexible center.
The Fr Unit
The fr unit represents a fraction of available space. Use it instead of percentages.
.grid {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
}The middle column is twice as wide as the sides. Grid calculates sizes after fixed and minimum constraints.
Why not percentages?
/* Percentages don't account for gaps */
.bad {
grid-template-columns: 33.333% 33.333% 33.333%;
gap: 1rem; /* now columns overflow */
}
/* Fr units handle gaps correctly */
.good {
grid-template-columns: 1fr 1fr 1fr;
gap: 1rem; /* columns fit perfectly */
}Repeat Function
Don't type the same value repeatedly.
/* Repetitive */
.grid {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}
/* Clean */
.grid {
grid-template-columns: repeat(5, 1fr);
}Mix repeat with other values:
.layout {
grid-template-columns: 250px repeat(3, 1fr) 250px;
}Auto-Fill and Auto-Fit
Create responsive grids without media queries.
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1rem;
}- auto-fill: Creates as many columns as fit, even if empty
- auto-fit: Creates columns only for content, collapses empty ones
Use auto-fit for cards and galleries. Items expand to fill available space.
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}Minmax Function
Set minimum and maximum sizes for tracks.
.grid {
grid-template-columns: minmax(200px, 300px) 1fr;
}The first column is never smaller than 200px or larger than 300px.
Common pattern for responsive content:
.container {
display: grid;
grid-template-columns: minmax(0, 1fr);
}The minmax(0, 1fr) prevents grid items from overflowing. By default, grid items won't shrink below their content size. Setting minimum to 0 allows shrinking.
Grid Lines and Placement
Grid creates numbered lines between tracks. Use them to place items.
.item {
grid-column: 1 / 3; /* spans from line 1 to line 3 */
grid-row: 1 / 2;
}Shorthand with span:
.item {
grid-column: span 2; /* spans 2 columns */
}Negative numbers count from the end:
.full-width {
grid-column: 1 / -1; /* start to end */
}Grid Template Areas
Name regions of your grid for semantic placement.
.layout {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar main aside"
"footer footer footer";
min-height: 100vh;
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.main {
grid-area: main;
}
.aside {
grid-area: aside;
}
.footer {
grid-area: footer;
}The ASCII-art structure makes the layout obvious. Change it at a breakpoint:
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"aside"
"footer";
}
}Implicit Grid
When items exceed defined rows/columns, grid creates implicit tracks.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
/* only defined columns, no rows */
}If you add 10 items, grid creates rows automatically. Control their size:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px; /* implicit rows are 200px */
}Use minmax for flexible implicit rows:
.grid {
grid-auto-rows: minmax(150px, auto);
}Alignment
Grid has alignment properties similar to flexbox.
.grid {
display: grid;
justify-items: center; /* align items horizontally */
align-items: center; /* align items vertically */
}Align the entire grid within its container:
.container {
display: grid;
grid-template-columns: repeat(3, 200px);
justify-content: center; /* center the grid horizontally */
gap: 1rem;
}Individual items override with justify-self and align-self:
.special {
justify-self: end;
align-self: start;
}Gap
Space between grid cells. Works like flexbox gap.
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}Different row and column gaps:
.grid {
row-gap: 2rem;
column-gap: 1rem;
}Subgrid
A grid item can inherit column or row tracks from its parent grid.
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}
.child {
display: grid;
grid-column: span 4;
grid-template-columns: subgrid; /* inherit parent's 4 columns */
}Useful for aligning nested content to the parent grid structure.
Grid vs Flexbox Decision Framework
Use Grid when:
- You need precise 2D control (rows AND columns)
- Layout is container-defined (you decide structure)
- Items need to align across rows/columns
- Overlapping content
- Complex page layouts
Use Flexbox when:
- One-dimensional arrangement
- Content size determines layout
- Navigation, button groups, toolbars
- Centering, space distribution
- Flexible ordering
Sometimes you'll use both:
/* Grid for page layout */
.page {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
/* Flexbox for header content */
.header {
display: flex;
justify-content: space-between;
align-items: center;
}Practical Example: Card Grid
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
padding: 2rem;
}
.card {
display: grid;
grid-template-rows: 200px auto 1fr auto;
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.card-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.card-title {
padding: 1rem;
font-size: 1.25rem;
font-weight: 600;
}
.card-content {
padding: 0 1rem;
}
.card-actions {
padding: 1rem;
display: flex;
gap: 0.5rem;
justify-content: flex-end;
}<div class="cards">
<article class="card">
<img src="image1.jpg" class="card-image" alt="">
<h3 class="card-title">Card Title</h3>
<div class="card-content">
<p>Card description goes here.</p>
</div>
<div class="card-actions">
<button>Read More</button>
</div>
</article>
<!-- more cards -->
</div>The outer grid creates responsive columns. Each card uses grid internally to ensure consistent heights and button alignment.
Check Your Understanding
What's the difference between auto-fit and auto-fill in repeat()?
Which unit automatically accounts for gap spacing?
Practice
Summary
- Two-dimensional: Control rows and columns simultaneously
- Grid container:
display: gridmakes direct children grid items - Fr unit: Represents fraction of available space, handles gaps correctly
- Repeat:
repeat(count, size)avoids repetition - Auto-fit/auto-fill: Responsive columns without media queries
- Minmax: Set minimum and maximum track sizes
- Grid lines: Numbered lines between tracks for precise placement
- Template areas: Named regions for semantic layout
- Implicit grid: Auto-created rows/columns for overflow content
- Gap: Spacing between cells, cleaner than margins
- Subgrid: Inherit parent grid tracks for nested alignment
- Use grid for: 2D layouts, galleries, page structure, overlapping content
- Use flexbox for: 1D layouts, navigation, button groups, content flow
Keep Practicing
Grid Garden ā A game where you grow a carrot garden by writing CSS grid code