CSS Subgrid Tutorial
Use CSS subgrid to align nested elements with their parent grid, perfect for card layouts, forms, and complex content where rows and columns must line up across components.
What you'll learn
- ✓What subgrid is and why it was added to CSS
- ✓How subgrid differs from a nested grid
- ✓Aligning card content across columns and rows
- ✓Forms with perfectly aligned labels and inputs
- ✓Browser support and fallbacks
Prerequisites
- •Comfortable with CSS Grid basics
What and Why
CSS Grid is wonderful, but it has a long-standing limitation: a nested grid does not know anything about its parent’s tracks. If you place three cards in a row and each card has a title, body, and footer, the titles will not align across cards unless every card happens to have the same content height. Subgrid fixes this by letting a child grid inherit its parent’s row or column tracks, so nested content lines up perfectly.
Mental Model
A subgrid is a grid container whose grid-template-rows or grid-template-columns is set to subgrid. That tells the browser to participate in the parent’s track system rather than creating new tracks. The child’s items still get placed normally, but the lines they snap to are the parent’s lines.
Parent grid: 3 columns x 3 rows
Nested grid in a cell:
creates its own tracks, no alignment with siblings
Subgrid in a cell:
reuses parent rows/cols
child items snap to parent lines
siblings line up across the layout
Hands-on Example
A card layout where title, body, and CTA align across three cards no matter the content length.
<ul class="cards">
<li class="card">
<h3>Starter</h3>
<p>For solo developers exploring the platform.</p>
<a href="#">Get started</a>
</li>
<li class="card">
<h3>Team</h3>
<p>For small teams that need shared workspaces and roles.</p>
<a href="#">Choose Team</a>
</li>
<li class="card">
<h3>Enterprise</h3>
<p>Custom contracts, SSO, and dedicated support.</p>
<a href="#">Talk to sales</a>
</li>
</ul>
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3;
padding: 1.5rem;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
}
The parent declares three rows: header, body, footer. Each card spans all three rows and uses grid-template-rows: subgrid, inheriting those tracks. Now titles line up across cards, descriptions occupy the same vertical band, and the CTAs sit on the same baseline. Without subgrid you would need flex tricks or fixed heights.
A common form pattern also benefits.
.form {
display: grid;
grid-template-columns: max-content 1fr;
gap: 0.5rem 1rem;
}
.field {
display: grid;
grid-template-columns: subgrid;
grid-column: span 2;
}
Each .field participates in the parent’s two-column track, so labels align in a single column even when wrapped in field components.
Common Pitfalls
The first pitfall is forgetting to span the parent tracks. A child with grid-template-rows: subgrid but grid-row: span 1 only subscribes to one row, which usually is not what you want. You almost always pair subgrid with an explicit grid-row or grid-column span that covers the area you want.
Another pitfall is assuming subgrid replaces flex. Subgrid is for alignment with a parent grid. For one-dimensional layouts like nav bars, flexbox is still simpler.
Gap values are not inherited by default for column gaps when only grid-template-rows: subgrid is used. If gaps look off, set both rows and columns to subgrid or explicitly declare gap on the parent.
Browser support is now strong in all evergreen browsers but always confirm against your supported matrix. For older browsers, design a graceful fallback that uses a regular nested grid or flex column, since the layout will degrade rather than break.
Best Practices
Use subgrid whenever you have a list of compound components that need consistent vertical or horizontal rhythm. Cards, tables of mixed components, forms with labels and inputs, and feature comparison layouts are classic fits. Keep the parent’s track definitions explicit so the subgrid contract is easy to read. Comment which rows mean what, since “auto 1fr auto” is opaque on its own.
Combine subgrid with CSS variables for sizing so adjustments stay in one place. And always test with the longest and shortest content you can imagine, since subgrid’s whole value shows up in those edge cases.
Wrap-up
Subgrid closes one of CSS Grid’s most painful gaps. With one declaration you can make nested components share their parent’s track system, eliminating a whole category of alignment hacks. Reach for it when card grids, forms, or comparison tables need to feel rigorously aligned. Once you internalize the mental model, you will spot uses for it everywhere.
Related articles
- HTML & CSS CSS Grid vs Flexbox: When to Use Each (with Examples)
Stop flipping a coin between Grid and Flexbox. Learn the mental model that picks the right layout tool every time, with practical CSS examples.
- HTML & CSS CSS Grid: A Practical Beginner's Guide
CSS Grid is the modern tool for two-dimensional layout. This guide covers tracks, the fr unit, gaps, spans, and responsive grids — everything you need to build real page layouts.
- HTML & CSS CSS Cascade Layers and Specificity: A Calmer Mental Model
Stop fighting !important. Learn how the CSS cascade, specificity, and the new @layer rule combine to give you predictable, maintainable styles.
- HTML & CSS CSS Container Queries Explained with Real Examples
Container queries let components style themselves based on their parent's size, not the viewport. Learn the syntax, the units, and when to use them.