Skip to content

CSS Subgrid: Aligning Nested Grids to Parent Tracks

CSS subgrid lets nested grids inherit the parent's tracks, so card titles, bodies, and footers line up across a whole grid. Support is 90%+ in 2026.

· · 7 min read
CSS subgrid layout code on a dark editor screen

Quick Take

CSS subgrid lets a nested grid borrow its parent's row or column tracks instead of creating its own, so elements inside separate children line up on the same lines. It's Baseline widely available and sits above 90% global support in 2026.

Quick take: - CSS subgrid lets a child grid reuse the row or column tracks defined on its parent instead of building its own. Set grid-template-columns: subgrid or grid-template-rows: subgrid on the child, and its contents snap to the parent's lines. That's how you get titles, body copy, and footers to line up across every card in a grid. Support is above 90% in 2026.

CSS subgrid solves one specific, annoying problem: nested grids don't share track lines with their parent, so content inside separate children drifts out of alignment. You set grid-template-rows: subgrid (or columns) on a grid item that is itself a grid, and its children start measuring against the parent's tracks. Subgrid is Baseline widely available and sits above 90% global support as of 2026. I reach for it any time a card layout needs pixel-perfect rows without me hard-coding heights.

What problem does CSS subgrid solve?

Picture a product grid. Each card holds a title, a description, and a price footer. The titles are different lengths - some wrap to two lines, some stay on one. The descriptions vary too. Without subgrid, each card is its own little grid, and each card sizes its rows from its own content. The result? Prices float at different heights. Titles push the body down by different amounts. The whole row looks crooked.

Here's the thing. The parent grid does know where the columns are, so the cards themselves line up left to right. But the parent has no idea what's happening inside each card. A child grid's rows are private. That internal misalignment is exactly what subgrid fixes.

/* The outer grid: three columns of cards */
.product-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

/* Each card is a normal grid here - and its rows DON'T match its neighbours */
.card {
  display: grid;
  grid-template-rows: auto 1fr auto;
}

That grid-template-rows: auto 1fr auto looks reasonable. But auto means "as tall as this card's title," which differs card to card. So the middle rows never agree.

How does the subgrid keyword work?

The fix is to give the outer grid explicit row tracks, then tell each card to inherit them. You do that with the subgrid keyword. When a grid item spans some of the parent's tracks and sets grid-template-rows: subgrid, it stops inventing its own rows. It adopts the parent's.

.product-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Define the shared rows ON THE PARENT */
  grid-template-rows: auto 1fr auto;
  gap: 1.5rem;
}

.card {
  display: grid;
  /* Span all three parent rows, then borrow them */
  grid-row: span 3;
  grid-template-rows: subgrid;
}

Now every card measures its title, body, and footer against the same three lines. The tallest title in the whole grid sets the height of the first row, and every other card respects it. Same for the body and footer. Notice the parent defines the tracks once, and the children just point at them with a single keyword. Isn't that cleaner than the alternative?

You can do the same on the column axis with grid-template-columns: subgrid, and you can use both at once. Each axis is independent.

A concrete building facade built from a repeating grid of panels next to a spiral staircase
Photo by Declan Sun on Unsplash

A card grid where three rows line up

Let me show the full thing - markup plus CSS - so the alignment is concrete. Three stacked rows (title, body, footer) that agree across all cards.

<div class="product-grid">
  <article class="card">
    <h3 class="card__title">Compact wide-angle lens for mirrorless bodies</h3>
    <p class="card__body">A short description that runs a couple of lines.</p>
    <div class="card__footer"><span>$249</span><button>Add</button></div>
  </article>

  <article class="card">
    <h3 class="card__title">Tripod</h3>
    <p class="card__body">A much longer description that keeps going and wraps onto three or even four lines depending on the width.</p>
    <div class="card__footer"><span>$79</span><button>Add</button></div>
  </article>
</div>
.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  grid-template-rows: auto 1fr auto;
  gap: 1.5rem;
}

.card {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  border: 1px solid #2a2a2a;
  border-radius: 8px;
  padding: 1rem;
}

.card__footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

The first card has a long two-line title and a short body. The second has a one-word title and a four-line body. Without subgrid, their footers would sit at wildly different heights. With it, the footers line up on the same baseline, and so do the titles. The gap between rows even inherits from the parent's gap, which is a nice touch a plain nested grid can't give you.

Subgrid vs nesting a normal grid

So when do you use which? A plain nested grid is the right call when a component's internal layout is nobody else's business - a settings panel, a form section, a self-contained widget. Its rows and columns should size from its own content, full stop.

Subgrid is the right call the moment children of different parents need to agree with each other. Card grids, comparison tables built from divs, timeline entries, any repeating unit where a shared baseline matters. The rule I use: if misalignment between siblings would look like a bug, reach for subgrid.

Before subgrid landed, I faked this with fixed heights. I'd set min-height: 3.2rem on every title so two-line and one-line titles occupied the same space, then pray nobody wrote a three-line title. It broke constantly. New copy came in, a title wrapped further than I'd budgeted, and the footers drifted again. Subgrid deletes that whole category of hack. My honest opinion? For any card grid with variable-length content, subgrid is worth it even at a small support cost - the fixed-height workaround is more fragile and needs babysitting every time the copy changes. For a one-off layout where nothing repeats, don't bother; a normal grid is simpler.

If you're still deciding between the two-dimensional power of Grid and the one-dimensional simplicity of Flexbox for the outer container itself, the CSS Grid vs Flexbox comparison walks through that decision with concrete examples.

A woven metallic building facade with a regular grid pattern against a clear blue sky
Photo by Maarten Deckers on Unsplash

Browser support and a graceful fallback

Subgrid has a longer history than people assume. Firefox shipped it back in version 71 in late 2019. Safari 16 added it in 2022, and Chrome 117 followed in September 2023, which is the moment it became Baseline "widely available." As of 2026, global support sits above 90% according to caniuse and MDN. That's production-ready for most audiences.

Still, 90-something percent isn't 100. Guard it with @supports so older browsers get a sane layout instead of a broken one.

.card {
  display: grid;
  grid-template-rows: auto 1fr auto; /* fallback: each card sizes itself */
}

@supports (grid-template-rows: subgrid) {
  .product-grid {
    grid-template-rows: auto 1fr auto;
  }
  .card {
    grid-row: span 3;
    grid-template-rows: subgrid; /* the shared-track upgrade */
  }
}

Browsers without subgrid keep the plain nested grid. The footers won't be perfectly aligned there, but the cards still stack cleanly and read fine. No JavaScript, no polyfill, no layout explosion. That's a graceful degrade, and for a purely cosmetic alignment feature it's exactly the right trade.

One last practical note. Subgrid only inherits tracks it actually spans, so the child has to grid-row: span N (or grid-column: span N) across the parent lines you want to borrow. Forget the span and the keyword quietly does nothing. Check the MDN subgrid reference if the alignment isn't taking - it's almost always a missing span.

Frequently Asked Questions

What does CSS subgrid actually do?
Subgrid lets a nested grid adopt the track sizes of its parent grid instead of defining its own. You set grid-template-columns or grid-template-rows to the keyword subgrid on a grid item that is itself a grid. Its children then align to the parent's lines, not to lines the child invented.
What is the difference between subgrid and a normal nested grid?
A normal nested grid sizes its tracks from its own content, so two sibling cards can end up with mismatched rows. Subgrid pulls the track definitions down from the parent, so every child shares the same lines. Use a nested grid when a component's internal layout is private, and subgrid when children must align with each other.
What is the browser support for CSS subgrid?
Subgrid shipped in Firefox 71 in 2019, then Safari 16 and Chrome 117 in 2023, which made it Baseline widely available by late 2023. Global support sits above 90% as of 2026 according to caniuse. That's high enough for production with a graceful fallback.
Can you use subgrid for both rows and columns?
Yes. You can set grid-template-columns: subgrid, grid-template-rows: subgrid, or both on the same element. Each axis is independent, so a card can inherit the parent's three row tracks while still defining its own columns.
How do I provide a fallback for browsers without subgrid?
Wrap the subgrid rules in @supports (grid-template-columns: subgrid). Browsers that lack support keep the plain nested-grid layout, which stacks and reads fine even if the rows don't align perfectly. No polyfill is needed for a graceful degrade.