CSS Grid solved most layout problems on its own, but one stubborn case remained: aligning content inside independently-sized nested grids, like a row of cards with varying content. Subgrid closes that gap.
1The Classic Card-Row Alignment Problem
Picture a row of pricing cards, each with a title, a variable-length description, and a footer button. If each card independently uses display: grid to lay out its own title/body/footer, every card's internal rows size purely based on that card's own content — a card with a longer title pushes its body down, while its neighbor's shorter title doesn't, breaking the visual alignment of the whole row.
Before subgrid, fixing this required either JavaScript measuring the tallest title across all cards and forcing a fixed height, or abandoning per-card grids in favor of one giant, harder-to-reason-about parent grid spanning every card's internals directly.
2How subgrid Solves It Directly
The parent grid defines the shared row tracks once — title row, body row, footer row — sized to fit the tallest content across all cards. Each card, instead of declaring its own independent grid-template-rows, sets grid-template-rows: subgrid and spans the appropriate number of parent rows with grid-row: span 3. The card's own children (title, body, footer) then align to those exact same parent-defined row lines as every sibling card's children.
The result: every card's title sits on the same line, every footer sits on the same line, regardless of how much content any individual card actually has — solved entirely in CSS, with zero JavaScript measurement.
3Named Lines Keep Deeply Nested Layouts Self-Documenting
When the parent grid names its tracks — [title-start] auto [body-start] 1fr [footer-start] auto [footer-end] — a subgrid automatically inherits those same named lines. A card's title element can then be placed with grid-row: title-start, using the exact same semantic vocabulary the parent grid defined, rather than reasoning about raw numeric line indices that shift if the grid structure changes.
This compounds well with larger design systems: a page-level layout grid can define named regions once, and every nested subgrid throughout the component tree can reference those same names consistently, keeping alignment intent readable even several nesting levels deep.
4Step-by-Step Breakdown
When A Nested Grid Needs To Line Up With Its Parent. Put a grid inside a grid item, and by default it creates its own independent set of tracks — completely unaware of the parent grid's column and row lines. subgrid changes that: a nested grid can adopt its parent's tracks directly, so content inside sibling cards finally aligns even when each card's internal content varies in length.
The Problem: Independent Nested Grids Don't Align. A row of cards, each internally using display: grid for its title/body/footer, will not align those internal rows across cards by default — one card's grid is entirely independent of its neighbor's, even though visually they're supposed to line up in a shared row.
The Misalignment Problem. Why don't three cards, each with display: grid and varying content, align their internal rows by default?
- →It's a browser rendering bug
- →Each nested grid establishes its own independent set of tracks, unaware of its siblings or parent
- →Grid can never align nested content; only Flexbox can
Adopting Parent Tracks With subgrid. Setting grid-template-columns: subgrid (or -rows) on a nested grid item tells it to adopt its parent's track definitions directly for that axis, instead of defining its own. The nested grid's own children then align to the exact same lines as their cousins in sibling cards.
Using subgrid. What does grid-template-rows: subgrid do on a nested grid item?
- →It creates a brand new, independent set of row tracks
- →It makes the nested grid adopt the row tracks of its parent grid directly
- →It disables grid layout on that element entirely
Named Lines Propagate Through Subgrid. A particularly powerful detail: named grid lines defined on the parent grid are inherited by a subgrid automatically, letting nested content reference the same semantic line names ([title-start], [footer-end]) as the outer grid, keeping the whole layout's structure self-documenting across nesting levels.
Named Line Inheritance. If a parent grid defines a named line like [title-start], can a subgrid's children reference that same name directly?
- →No — named lines must be redeclared inside the subgrid
- →Yes — subgrid inherits the parent's named lines automatically
- →Only if the subgrid explicitly renames them first
Subgrid Alignment Mastered. You now understand why nested grids misalign by default, how subgrid lets a nested grid adopt its parent's exact tracks, and how named grid lines propagate through subgrid to keep deeply nested layouts semantically consistent.
Inherit The Parent Grid's Tracks. grid-template-columns: subgrid lets a nested grid align to its parent grid's column tracks exactly.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Subgrid Should Not Change The Underlying DOM Or Reading Order
Subgrid only affects visual track alignment; the actual source order of cards and their content should still make logical sense when read linearly, since that source order is what determines screen reader and keyboard tab sequence.
2Consistent Visual Alignment Achieved Via Subgrid Can Improve Scannability For Low-Vision Users
Reliably aligned titles, bodies, and footers across a row of cards make the page easier to visually scan for users with low vision or cognitive load concerns, compared to a visually jagged, misaligned card row.
SEO Implications
- 1
Subgrid Eliminates JavaScript Height-Matching Previously Used For Card Alignment
Removing a JS-based 'measure the tallest card and force equal heights' script reduces main-thread work and layout thrashing, both of which factor into Core Web Vitals metrics.
- 2
CSS-Only Alignment Avoids Content Reflow Caused By Post-Load JavaScript Measurement
JS-based height-matching typically runs after initial render, causing a visible reflow; subgrid achieves the same alignment in the initial layout pass, avoiding that visual shift entirely.
Best Practices
Reach For Subgrid Before Reaching For A JavaScript Height-Matching Library
It solves the exact same problem natively, with better performance and no post-load reflow, for any browser supporting CSS Grid Level 2.
Name Your Parent Grid's Tracks When Using Subgrid Across Multiple Nesting Levels
Named lines propagate automatically and keep deeply nested layout code readable, instead of forcing every nested component to reason about raw numeric line positions.
Frequent Bugs
A subgrid item's content doesn't align with its siblings despite using grid-template-rows: subgrid.
Confirm the item also has the correct grid-row (or grid-column) span matching the number of parent tracks it should adopt — subgrid alone without the right span doesn't establish the relationship.
Rows in a subgridded card don't seem to inherit the expected sizing from the parent.
Double check the axis: subgrid must be declared on the same axis (rows vs columns) you're trying to inherit — declaring grid-template-columns: subgrid does nothing for row alignment.
Real-World Examples
A Pricing Card Row With Aligned Internals
Three pricing cards with varying description lengths, using subgrid so every card's title, price, feature list, and CTA button align perfectly across the row.
.pricing-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: auto auto 1fr auto; }
.pricing-card { grid-row: span 4; display: grid; grid-template-rows: subgrid; }