CSSSubgrid

Subgrid

Nested grids have a long-standing problem: a grid item that is itself display: grid creates a brand new, independent grid — its rows and columns have no relationship to the parent's tracks. subgrid fixes exactly this by letting a nested grid adopt its parent's track sizing instead of defining its own.

The Problem: Nested Grids Don't Align

Picture a row of cards, each internally laid out as its own small grid (image, title, description, button). Without subgrid, each card's internal grid sizes its own rows independently — so if one card's title wraps to two lines, that card's other rows shift out of alignment with its neighbors, even though all the cards share the same outer grid.

CSS
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.card {
  display: grid; /* an independent grid — NOT aligned to .cards' rows */
  grid-template-rows: auto auto 1fr auto;
  gap: 8px;
}
/* If one card's title wraps to 2 lines, its rows below no longer
   line up with the rows of the cards next to it. */
The Fix: grid-template-columns / rows: subgrid

Instead of declaring its own track sizes, a subgrid item inherits the track boundaries from the corresponding lines of its parent grid. This requires the item to actually span multiple parent tracks (via grid-row/grid-column), since a subgrid only makes sense across the tracks it participates in.

CSS
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto auto 1fr auto; /* the shared row rhythm */
  gap: 24px;
}

.card {
  display: grid;
  grid-row: span 4;              /* participate in 4 parent row tracks */
  grid-template-rows: subgrid;   /* adopt those 4 tracks' exact sizing */
  gap: 8px; /* subgrid can still define its own gap */
}

.card__image  { grid-row: 1; }
.card__title  { grid-row: 2; }
.card__body   { grid-row: 3; }
.card__button { grid-row: 4; }

HTML
<div class="cards">
  <div class="card">
    <img class="card__image" src="a.jpg" alt="" />
    <h3 class="card__title">A short title</h3>
    <p class="card__body">Some body copy.</p>
    <button class="card__button">Buy</button>
  </div>
  <div class="card">
    <img class="card__image" src="b.jpg" alt="" />
    <h3 class="card__title">A much longer title that wraps onto two lines</h3>
    <p class="card__body">Some other body copy.</p>
    <button class="card__button">Buy</button>
  </div>
</div>

Now every card's image row, title row, body row, and button row are sized by the outer grid's row tracks. If one card's title wraps to two lines, the whole row of cards grows that title row together — every image, body, and button row still lines up perfectly across all cards, with zero JavaScript and no fixed heights.

Rows and Columns Independently

subgrid is set per-axis. You can adopt the parent's column tracks, row tracks, both, or neither — mixing subgrid on one axis with an independent track list on the other:

CSS
.card {
  display: grid;
  grid-column: span 2;
  grid-row: span 4;
  grid-template-columns: subgrid;      /* inherit parent's columns */
  grid-template-rows: 40px 1fr 1fr auto; /* but define its own row sizes */
}
Check browser support before relying on subgrid
Subgrid is supported in all current major evergreen browsers (Chrome, Firefox, Safari) as of recent versions, but it landed later than the rest of Grid — if your project has to support older browser versions or you rely on subgrid for something layout-critical, verify support for your actual audience and have a graceful fallback (a plain nested grid still works, it simply won't row-align across siblings).
  • A subgrid item must span multiple tracks of the parent grid via grid-row/grid-column — subgrid has nothing to inherit if it only occupies a single cell.

  • Named lines on the parent grid remain visible and usable inside a subgrid, which is handy for consistent naming across nesting levels.

  • Subgrid solves the "cards in a row don't line up" problem far more directly than manual height-matching hacks or JS-based equal-height scripts.

Not the same as inheriting sizes into a totally separate grid
Subgrid doesn't just copy the parent's numbers — it creates a live structural relationship. If the parent grid's tracks resize (a responsive column width change, for example), the subgrid's tracks resize with them automatically.
Next
Zoom out from Grid to responsive spacing that scales with the viewport: [Fluid Spacing & Sizing](/css/fluid-spacing).