Subgrid
The Problem
CSS Grid is excellent for laying out direct children, but nested elements cannot participate in the parent grid's track sizing. This makes it impossible to align content across sibling components — for example, ensuring card titles, descriptions, and buttons all align at the same vertical position across a row of cards. AI agents almost never use subgrid and instead resort to fixed heights, JavaScript-based alignment, or complex workarounds that break with dynamic content.
The Solution
The subgrid value for grid-template-columns and/or grid-template-rows allows a nested grid to inherit its parent's track definitions. The child grid participates in the parent's track sizing, so content across sibling grid items aligns naturally without fixed dimensions or duplication of track definitions.
Code Examples
Card Layout with Aligned Content
The most common subgrid use case: ensuring headings, content, and footers align across cards.
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;
}
.card {
display: grid;
/* Inherit parent's row tracks for this card's internal layout */
grid-row: span 3;
grid-template-rows: subgrid;
gap: 0.75rem;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 1.5rem;
}
.card h2 {
/* Row 1: title — aligns across all cards */
align-self: start;
}
.card p {
/* Row 2: description — aligns across all cards */
align-self: start;
}
.card .action {
/* Row 3: button — pushed to bottom, aligned across all cards */
align-self: end;
}
<div class="card-grid">
<article class="card">
<h2>Short Title</h2>
<p>Brief description.</p>
<a class="action" href="#">Read more</a>
</article>
<article class="card">
<h2>A Much Longer Card Title That Wraps</h2>
<p>This card has a longer title, but the description and button still align with the other cards.</p>
<a class="action" href="#">Read more</a>
</article>
<article class="card">
<h2>Medium Title</h2>
<p>Another card with varying content length.</p>
<a class="action" href="#">Read more</a>
</article>
</div>
Subgrid for Columns
Align nested form labels and inputs to the parent grid's columns.
.form-grid {
display: grid;
grid-template-columns: 120px 1fr;
gap: 1rem;
}
.field-group {
display: grid;
grid-column: 1 / -1;
grid-template-columns: subgrid;
align-items: center;
}
.field-group label {
grid-column: 1;
}
.field-group input {
grid-column: 2;
}
<form class="form-grid">
<div class="field-group">
<label for="name">Name</label>
<input id="name" type="text" />
</div>
<div class="field-group">
<label for="email">Email</label>
<input id="email" type="email" />
</div>
<div class="field-group">
<label for="phone">Phone</label>
<input id="phone" type="tel" />
</div>
</form>
Two-Dimensional Subgrid
Inherit both rows and columns from the parent grid.
.dashboard {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
.widget {
display: grid;
grid-column: span 1;
grid-row: span 3;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}
.widget header {
/* Aligns with other widgets' headers */
font-weight: bold;
border-bottom: 1px solid #e5e7eb;
padding-bottom: 0.5rem;
}
.widget footer {
/* Aligns with other widgets' footers */
font-size: 0.875rem;
color: #6b7280;
}
Subgrid with Named Lines
Named lines from the parent grid flow through to the subgrid.
.page-layout {
display: grid;
grid-template-columns:
[full-start] 1fr
[content-start] minmax(0, 65ch)
[content-end] 1fr
[full-end];
}
.article {
display: grid;
grid-column: full-start / full-end;
grid-template-columns: subgrid;
}
.article p {
grid-column: content-start / content-end;
}
.article .wide-image {
grid-column: full-start / full-end;
}
Subgrid Without Duplicating Gap
The subgrid inherits the parent's gap by default. You can override it if needed.
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 2rem;
}
.child {
display: grid;
grid-column: span 2;
grid-template-columns: subgrid;
/* Subgrid inherits parent's 2rem gap */
/* Override if needed: */
gap: 0.5rem;
}
Browser Support
- Chrome 117+
- Edge 117+
- Safari 16+
- Firefox 71+
Global support exceeds 97%. Firefox was the first to ship subgrid in December 2019. Safari followed in September 2022, and Chrome/Edge added support in September 2023. Subgrid is safe for production use.
Common AI Mistakes
- Not using
subgridat all — most AI agents generate grid layouts with duplicated track definitions or fixed heights for alignment - Duplicating
grid-template-columnsvalues in child grids instead of usingsubgrid - Using JavaScript or fixed dimensions to align content across sibling grid items
- Not spanning the child grid item across the correct number of parent tracks before applying
subgrid - Forgetting that subgrid inherits the parent's
gapvalue (it can be overridden) - Applying
subgridwithout settingdisplay: gridon the child element first - Not leveraging subgrid for form layouts where labels and inputs need consistent alignment
When to Use
- Card grids where titles, content, and actions must align across cards
- Form layouts where labels and inputs align to a shared column track
- Dashboard widgets that share a common header/content/footer structure
- Full-bleed content layouts where nested elements need to reference the parent grid's named lines
- Any layout where nested elements need to participate in the parent grid's track sizing