Skip to content
C Codeloom
HTML & CSS

CSS Subgrid Tutorial

Use CSS subgrid to align nested elements with their parent grid, perfect for card layouts, forms, and complex content where rows and columns must line up across components.

·4 min read · By Codeloom
Intermediate 8 min read

What you'll learn

  • What subgrid is and why it was added to CSS
  • How subgrid differs from a nested grid
  • Aligning card content across columns and rows
  • Forms with perfectly aligned labels and inputs
  • Browser support and fallbacks

Prerequisites

  • Comfortable with CSS Grid basics

What and Why

CSS Grid is wonderful, but it has a long-standing limitation: a nested grid does not know anything about its parent’s tracks. If you place three cards in a row and each card has a title, body, and footer, the titles will not align across cards unless every card happens to have the same content height. Subgrid fixes this by letting a child grid inherit its parent’s row or column tracks, so nested content lines up perfectly.

Mental Model

A subgrid is a grid container whose grid-template-rows or grid-template-columns is set to subgrid. That tells the browser to participate in the parent’s track system rather than creating new tracks. The child’s items still get placed normally, but the lines they snap to are the parent’s lines.

Parent grid: 3 columns x 3 rows

Nested grid in a cell:
creates its own tracks, no alignment with siblings

Subgrid in a cell:
reuses parent rows/cols
child items snap to parent lines
siblings line up across the layout
Subgrid vs nested grid

Hands-on Example

A card layout where title, body, and CTA align across three cards no matter the content length.

<ul class="cards">
  <li class="card">
    <h3>Starter</h3>
    <p>For solo developers exploring the platform.</p>
    <a href="#">Get started</a>
  </li>
  <li class="card">
    <h3>Team</h3>
    <p>For small teams that need shared workspaces and roles.</p>
    <a href="#">Choose Team</a>
  </li>
  <li class="card">
    <h3>Enterprise</h3>
    <p>Custom contracts, SSO, and dedicated support.</p>
    <a href="#">Talk to sales</a>
  </li>
</ul>
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: auto 1fr auto;
  gap: 1rem;
}

.card {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
  padding: 1.5rem;
  border: 1px solid #e5e7eb;
  border-radius: 0.5rem;
}

The parent declares three rows: header, body, footer. Each card spans all three rows and uses grid-template-rows: subgrid, inheriting those tracks. Now titles line up across cards, descriptions occupy the same vertical band, and the CTAs sit on the same baseline. Without subgrid you would need flex tricks or fixed heights.

A common form pattern also benefits.

.form {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.5rem 1rem;
}
.field {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: span 2;
}

Each .field participates in the parent’s two-column track, so labels align in a single column even when wrapped in field components.

Common Pitfalls

The first pitfall is forgetting to span the parent tracks. A child with grid-template-rows: subgrid but grid-row: span 1 only subscribes to one row, which usually is not what you want. You almost always pair subgrid with an explicit grid-row or grid-column span that covers the area you want.

Another pitfall is assuming subgrid replaces flex. Subgrid is for alignment with a parent grid. For one-dimensional layouts like nav bars, flexbox is still simpler.

Gap values are not inherited by default for column gaps when only grid-template-rows: subgrid is used. If gaps look off, set both rows and columns to subgrid or explicitly declare gap on the parent.

Browser support is now strong in all evergreen browsers but always confirm against your supported matrix. For older browsers, design a graceful fallback that uses a regular nested grid or flex column, since the layout will degrade rather than break.

Best Practices

Use subgrid whenever you have a list of compound components that need consistent vertical or horizontal rhythm. Cards, tables of mixed components, forms with labels and inputs, and feature comparison layouts are classic fits. Keep the parent’s track definitions explicit so the subgrid contract is easy to read. Comment which rows mean what, since “auto 1fr auto” is opaque on its own.

Combine subgrid with CSS variables for sizing so adjustments stay in one place. And always test with the longest and shortest content you can imagine, since subgrid’s whole value shows up in those edge cases.

Wrap-up

Subgrid closes one of CSS Grid’s most painful gaps. With one declaration you can make nested components share their parent’s track system, eliminating a whole category of alignment hacks. Reach for it when card grids, forms, or comparison tables need to feel rigorously aligned. Once you internalize the mental model, you will spot uses for it everywhere.