Skip to content
The modern web platformLesson 4 of 7Intermediate12 min

CSS Subgrid

Subgrid lets a nested element adopt its parent's grid tracks, so content inside a row of cards lines up across them with no fixed heights or magic numbers.

Kept on this device only.

In one line: subgrid lets a grid item borrow its parent grid's rows or columns, so the things inside a row of cards — titles, bodies, footers — align across every card without you hand-tuning a single height.

What it is

CSS Grid is great at laying out a row of cards. The problem is everything inside each card: one title wraps to two lines, the next to one, so the bodies start at different heights and the footers drift. Each card is its own grid, ignorant of its neighbours.

Subgrid fixes that. When you set grid-template-rows: subgrid (or grid-template-columns: subgrid) on a grid item that itself is a grid, that item stops defining its own tracks and instead adopts the tracks of the parent grid it spans. Now the title row, body row, and footer row are shared across the whole outer row, and everything lines up.

Why it matters

Before subgrid, alignment across cards meant fixed heights (min-height: 3rem on every title) that break the moment content changes language or length — the classic "magic number" that rots. Subgrid makes alignment a property of the layout, not a guess: the browser measures the tallest title in the row and gives every card the same title track, automatically and responsively.

It is now Baseline across modern browsers, so it is a real production tool, not a future bet — with a clean flexbox fallback for the long tail.

See it

Live demo
Tweak it2
3
Toggle subgrid on and off across a row of uneven cards — watch the rows line up or drift.

Toggle subgrid off and the cards size their rows independently — titles and tags drift out of line. Toggle it on and every region snaps to a shared track, however uneven the content.

How it works

Two grids cooperate:

  • The outer grid is the row. Give it columns and, crucially, named or implicit rows the cards can share — e.g. three rows for title / body / footer.
  • Each card is a grid item that spans those rows (grid-row: span 3) and is itself a grid declaring grid-template-rows: subgrid. That one keyword means "don't invent rows; use the three the parent already defined."

The card's own children then place onto the parent's tracks. Because all cards share the same parent rows, the browser sizes each track to the tallest content across the whole row — that is where the alignment comes from. Gaps (gap) are inherited from the parent too, so spacing stays consistent.

Build it

HTML — a list of cards, each with three regions
<ul class="cards">
  <li class="card">
    <h3>Quick note</h3>
    <p>Short body.</p>
    <span class="tag">Note</span>
  </li>
  <li class="card">
    <h3>A longer card title that wraps onto two lines</h3>
    <p>A longer body that runs on for several lines so the natural heights differ.</p>
    <span class="tag">Article</span>
  </li>
</ul>

Make it yours

Use the controls beside the demo above to change subgrid and cards in the row — each change updates the example live.

Experiment in the playground
  • Turn subgrid off and watch the footers drift — that ragged baseline is exactly what fixed min-height hacks try (and fail) to tame.
  • Add a card to the row and the shared tracks re-measure to the new tallest content. No value to update.
  • Picture a card with a much longer title: every card's title row grows together, so the bodies still start on the same line.

Reproduce it with an LLM

Reproduce it with an LLM

You are a senior front-end engineer. Build a responsive row of product cards where each card has a title (1–2 lines), a body, and a footer with a price and button. Use CSS Grid with `grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr))` for the row, then make each card a grid item that spans the row's tracks with `grid-row: span 3` and `grid-template-rows: subgrid`, so titles, bodies, and footers line up across every card regardless of content length — no fixed heights or magic numbers. Provide a graceful fallback with `@supports not (grid-template-rows: subgrid)` using flexbox. Semantic HTML (a list of articles), and a visible focus style on the buttons. Return only the HTML and CSS.

Pitfalls & accessibility

Further reading