Learn how the CSS Grid subgrid feature allows grid items to inherit and align with their parent grid tracks, solving complex card layout alignment challenges.

Mark it as completed to track your progress, or bookmark it to review later.
Join senior engineers who receive practical, deep-dive frontend challenges, detailed concepts, and blueprints directly in their inbox.
We value your privacy. Unsubscribe at any time.
Expand your mastery. Deep dive into other frontend interview challenges in this category.
Deep dive into CSS container queries and style queries. Learn size queries, style queries evaluating CSS Custom Properties, preventing infinite layout loops, and component design patterns.
Master the low-level CSS Houdini Paint API and Typed Object Model (Typed OM). Learn how to register custom properties, construct Paint Worklets, and draw high-performance custom backgrounds.
A common challenge in frontend layouts is aligning internal elements of separate card components. For example, if you have a row of card elements with dynamic content, you want their headers, images, bodies, and footers to align horizontally across cards, regardless of content size differences.
Historically, this required rigid heights or complex JavaScript solutions. Modern CSS introduces Subgrid to solve this exact issue.
Consider a standard three-column card row. Each card contains a title, a brief description, and a footer button:
<div class="grid-container">
<div class="card">
<h3>Short Title</h3>
<p>Brief text description.</p>
<button>Footer Button</button>
</div>
<div class="card">
<h3>A Much Longer Title That Wraps to Two Lines</h3>
<p>A longer text description that occupies more space vertically.</p>
<button>Footer Button</button>
</div>
<div class="card">
<h3>Title</h3>
<p>Short desc.</p>
<button>Footer Button</button>
</div>
</div>If we make the .grid-container a grid, the cards themselves align perfectly. However, the internal headers, paragraph text, and buttons do not. If Card 2's header wraps to two lines, Card 1's description will still start higher, breaking horizontal reading alignment across the cards.
Subgrid allows child elements of a grid item (grand-children of the parent grid container) to opt-in to the parent grid's column or row tracks.
Here is the modern CSS way to solve this:
/* Parent Grid Container */
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
/* Card item (child of grid-container, parent of internal elements) */
.card {
display: grid;
/* Occupy three rows in the parent grid layout */
grid-row: span 3;
/* Opt-in to inherit the row definitions of the parent grid */
grid-template-rows: subgrid;
gap: 10px;
}.grid-container defines columns, but leaves rows to grow implicitly.grid-row: span 3) within the parent container.grid-template-rows: subgrid. Instead of defining its own row heights, it hands control over to the parent grid container.Subgrid works just as well for columns. If you want child elements of a component to align perfectly with the parent column structure, specify subgrid on columns:
.sidebar-wrapper {
display: grid;
grid-column: span 2;
/* Inherit columns from the parent layout grid */
grid-template-columns: subgrid;
}CSS Subgrid is now widely supported in all modern greenfield browsers (Chrome, Safari, Firefox, Edge).
To ensure layouts remain usable on legacy browsers, use a feature query to wrap subgrid styles:
.card {
display: flex;
flex-direction: column;
justify-content: space-between;
}
@supports (grid-template-rows: subgrid) {
.grid-container {
/* Define row tracks for child contents */
grid-auto-rows: auto auto auto;
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
}
}grid-template-rows or grid-template-columns that allows a nested grid container to use the track lines defined on its parent grid container.grid-row: span N or grid-column: span N to declare how many tracks the subgrid spans, then specify grid-template-rows: subgrid or grid-template-columns: subgrid on the child container.