What Is CSS Subgrid? Nested Grid Alignment Explained
CSS subgrid lets a nested grid item inherit its parent's track sizing, so children can align to the same columns or rows across unrelated containers.
CSS subgrid is a value for grid-template-columns and grid-template-rows that lets a nested grid item inherit the track definitions of its parent grid, instead of defining its own independent set of tracks. It solves a specific alignment problem that CSS Grid on its own couldn’t: getting content inside nested elements to line up with the outer grid’s columns or rows.
The problem subgrid solves
Standard CSS Grid is powerful for laying out a single level of items, but each grid you define is self-contained. If you put a grid item inside another grid item and turn that child into a grid of its own, it has no awareness of the parent’s track sizes. Its columns are calculated independently, based on its own content and width — not the parent’s.
This becomes a real problem with card layouts. Imagine a row of product cards, each containing a title, a description, and a price, where you want the titles across all cards to align to the same baseline, the descriptions to align to another, and so on — even though each card is really a small grid nested inside a larger one. Without subgrid, each card’s internal grid sizes its rows independently based on its own content, so a card with a long title pushes its own description down without affecting its neighbors, and nothing lines up across cards.
Before subgrid, working around this required hacks: matching heights with JavaScript, using a single flat grid for the entire layout instead of nested components, or accepting misaligned content. Subgrid makes the natural component structure — a grid of cards, each internally a grid — actually align the way you’d expect.
How to use it
To use subgrid, a nested grid item declares display: grid and sets grid-template-columns: subgrid or grid-template-rows: subgrid instead of specifying its own track sizes:
.card-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: subgrid;
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
}
Here, each .card spans three rows of the parent grid and uses subgrid to inherit exactly those row tracks, rather than sizing its own three rows based on its own content. The result: a title row, description row, and price row that all align across every card in the row, because they’re really the same set of grid lines shared by every card.
Subgrid can be applied to rows, columns, or both. A subgridded axis inherits the parent’s track sizes and line names on that axis; the other axis (if not also subgridded) is sized independently as normal.
Subgrid and gap
One subtlety: by default, a subgrid also inherits the parent’s gap value on the subgridded axis, unless you explicitly override it. This is usually what you want — consistent spacing between the outer grid’s columns should typically match the spacing used inside nested subgrids — but it’s worth setting explicitly if your design calls for different spacing at different nesting levels.
Subgrid vs a flat grid
A common question is whether subgrid is even necessary — couldn’t you just use one large, flat grid for the whole layout instead of nesting? The two approaches solve overlapping problems but suit different layouts.
| Flat grid | Subgrid | |
|---|---|---|
| Markup structure | Everything is a direct child of one grid container | Preserves natural component nesting (cards, list items) |
| Reusability | Layout logic is tied to one container’s markup | Each nested component can be reused elsewhere, independent of the parent |
| Alignment across items | Automatic, since everything shares one grid | Requires explicit subgrid declarations at each level |
| Complexity for deeply nested UI | Gets unwieldy fast | Scales more cleanly through multiple levels |
If your components need to be reusable outside their current context — a card component used in a grid here and a flex row somewhere else — subgrid keeps the component’s internal structure self-contained while still allowing alignment when it happens to sit inside a matching parent grid. A flat grid forces every piece of content to live directly under one container, which works for simple layouts but breaks down for component-based UIs.
Where it fits with the rest of CSS layout
Subgrid is a layout feature, not a replacement for the rest of the grid or container query toolkit — it’s specifically about track inheritance between nested grids. It composes well with other modern CSS: you might use container queries to decide how many columns a card row shows at a given size, CSS nesting to keep the card’s own selectors organized, and subgrid to keep the cards’ internal rows aligned once the column count is decided. None of these features depend on the others, but they’re designed to be combined.
The takeaway
Subgrid closes a real gap in CSS Grid: it lets a nested grid item share its parent’s exact track sizing instead of calculating its own, which is what makes content inside independently-styled components — cards, list rows, form fields — align across siblings the way a single flat grid always could. Reach for it whenever you have grid-based components nested inside a grid-based layout and need their internal rows or columns to line up without collapsing your markup into one giant, unreusable grid.
Tagged
Keep reading
Takina · · 4 min read CSS field-sizing Property Explained
The CSS field-sizing property lets form controls like textareas grow to fit their content automatically, without JavaScript resize listeners.
Takina · · 3 min read CSS Scrollbar Styling: scrollbar-color and scrollbar-width
CSS now styles scrollbars natively with scrollbar-color and scrollbar-width, replacing years of vendor-prefixed hacks. Here's how they work.
Takina · · 4 min read The CSS color-scheme Property, Explained
CSS color-scheme tells the browser which themes a page supports so native form controls, scrollbars, and UI render in dark mode without extra CSS.