Section 2 · Layout That Holds Up
Subgrid for Aligned Cards
17 min3 min readCode playground
Lesson at a glance
Use subgrid so the time, title, abstract and room of every session card line up across a row of cards, whatever the length of each title.
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
Put three Waypoint session cards side by side and the problem jumps out. One title fits on a line, one wraps to two, one to three. Each card lays out its own content, so the abstracts start at three different heights and the room labels at the bottom form a staircase. Designers notice. Users notice less, but the page looks unfinished.
The old fixes were fixed heights (which break with real content) or JavaScript that measures every title. Subgrid makes the cards share one set of rows.
Why nested grids don’t line up
When a card becomes display: grid, it creates its own, independent tracks. Its title row is as tall as its title; the neighbouring card’s title row is as tall as that title. Nothing connects them, because each card only knows about its own content.
What you want is for the “title row” to be one track shared across all cards in the same visual row, sized by the tallest title. That shared track has to live in the parent, the .sessions grid, and the cards need to borrow it.
Borrowing the parent’s rows
.sessions {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr));
gap: 24px;
}
.session-card {
display: grid;
grid-row: span 4; /* time, title, abstract, room */
grid-template-rows: subgrid; /* use the parent's four rows */
row-gap: 8px; /* tighter than the parent's 24px */
}Two declarations do the work. grid-row: span 4 makes each card occupy four rows of the parent grid. grid-template-rows: subgrid tells the card not to create its own rows but to use the four it spans. The card’s four children (time, title, abstract, room) are placed into those parent rows in order.
Now the browser sizes each parent row by the tallest content placed in it from every card in that row. The title track grows to fit the three-line title, the shorter titles get the same track, and every abstract starts at the same line. Room labels line up at the bottom.
Notice that the parent never declares grid-template-rows. It doesn’t need to: the cards’ spans create implicit rows, and those rows are sized from the content the subgrids place in them. Every new row of cards gets its own four tracks, so cards in the second visual row align with each other but not with the first row, which is what you want.
Gaps, lines and columns
A subgrid inherits the parent’s gap. Here the parent uses 24px between cards, which is far too much between a title and its abstract, so the card overrides row-gap for its own tracks. The space between cards is unaffected.
Subgrid works on columns too. A classic case on Waypoint is the speaker profile form: labels in one column, inputs in the next, and every label column the same width across several fieldsets. Making each fieldset grid-column: span 2; grid-template-columns: subgrid gives every fieldset the outer form’s columns, so labels align all the way down. Named grid lines from the parent are also visible inside the subgrid, so grid-column: content-start / content-end keeps working one level down.
Your turn
The exercise gives you three session cards with titles of different lengths. Turn each card into a row subgrid so that abstracts and room labels line up across the row. The checks compare the vertical positions of those parts across cards. The next lesson stays with sizing: min(), max(), clamp() and the keywords that let content decide how big things are.
Key takeaways
- A nested grid with
grid-template-rows: subgriduses its parent’s row tracks instead of creating its own, so content in sibling cards shares the same rows. - The subgridded item must span as many parent tracks as it has parts, for example
grid-row: span 4for a four-part card. - A subgrid inherits the parent’s gap by default and can override it with its own
row-gaporcolumn-gap. - Subgrid has been Baseline since September 2023 and widely available since March 2026, so aligned card layouts no longer need fixed heights or JavaScript measuring.