CSS Subgrid
Align nested grid items to a parent grid track, solving the classic card alignment problem without extra markup.
Overview
Key Points
- •subgrid is a value for grid-template-columns or grid-template-rows on a grid item that is also a grid container
- •The subgrid child inherits the track sizes and gaps from the parent grid
- •The subgrid item must span enough parent tracks to have tracks to inherit
- •Gaps are also inherited from the parent grid; you can override with gap on the subgrid
- •Named grid lines from the parent are available inside the subgrid
- •subgrid works on both row and column axes independently
- •Supported in Chrome 117+, Firefox 71+, Safari 16+
- •The classic use case: card grids where title, body, and footer align across columns
Examples
Card grid with aligned rows using subgrid
/* Parent grid with 3 columns and implicit row tracks */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto;
gap: 20px;
}
/* Each card spans 3 row tracks and uses subgrid */
.card {
grid-row: span 4; /* image, title, body, footer */
display: grid;
grid-template-rows: subgrid;
border: 1px solid #e5e7eb;
border-radius: 12px;
overflow: hidden;
}
/* Card children now align with siblings in other cards */
.card-image { /* row 1 */ aspect-ratio: 16/9; object-fit: cover; }
.card-title { /* row 2 */ padding: 16px 16px 0; font-weight: 700; }
.card-body { /* row 3 */ padding: 8px 16px; font-size: 0.875rem; color: #6b7280; }
.card-footer { /* row 4 */ padding: 0 16px 16px; }Without subgrid, cards with short titles push footers to different heights. Subgrid locks all footers to the same row line.
Subgrid on both axes for a form layout
.form-grid {
display: grid;
grid-template-columns: max-content 1fr;
gap: 12px 16px;
padding: 24px;
background: white;
border-radius: 12px;
}
/* A fieldset spans both columns and subgrids both axes */
.field-group {
grid-column: 1 / -1;
display: grid;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
grid-row: span 2;
gap: inherit; /* reuse parent gap */
}
.field-group label {
grid-column: 1;
align-self: center;
font-weight: 500;
color: #374151;
}
.field-group input {
grid-column: 2;
padding: 8px 12px;
border: 1px solid #d1d5db;
border-radius: 6px;
}Named lines with subgrid
.page {
display: grid;
grid-template-columns:
[full-start] 1fr
[content-start] min(65ch, 100%)
[content-end] 1fr
[full-end];
}
/* Subgrid inherits named lines */
.article {
grid-column: full;
display: grid;
grid-template-columns: subgrid;
}
/* Article children can reference parent named lines */
.article-text { grid-column: content; }
.article-pullout { grid-column: full; } /* bleeds to edge */Named lines from the parent grid are accessible inside a subgrid, enabling powerful editorial layout patterns.
Common Mistakes
- Setting grid-template-rows: subgrid without giving the item enough grid-row span to cover the needed tracks
- Expecting subgrid to create new tracks (it only inherits existing parent tracks)
- Forgetting that the subgrid item still needs to span the parent tracks with grid-row or grid-column
- Using gap on a subgrid and expecting it to be independent (it overrides the inherited gap)
Note
A quick test: add a red outline to all card children and check if titles and footers line up horizontally. If they do not, you need subgrid. If they do, they are already aligning via flex or fixed heights.
Exercises
Write CSS to style the HTML scaffold. The preview updates live — when it looks right, mark as done.
Completed: 0 / 2 exercises
Knowledge Check
Question 1 of 3