Combining Subgrid and Masonry for Complex Grid Layouts
AI generated
{ }
@
CSS · Grid · Subgrid · Masonry
Combining Subgrid and Masonry
Card grids with uneven heights that still keep their inner elements aligned

Masonry layout packs cards of different heights tightly together, subgrid precisely aligns inner elements to the track grid of a parent grid. Combined, the two techniques solve a problem that plain flexbox or a simple grid alone cannot, but only with a clear understanding of what masonry actually supports today and what it does not.

17 min read grid-template-rows: masonry subgrid · browser support reality

1. The problem: uneven card heights that still need aligned content

A card grid of article previews with varying text length produces either large gaps with classic CSS grid, when every row stretches to the tallest card, or a messy picture when cards flow freely. A Pinterest-style masonry layout packs each card into the currently shortest column, avoiding unnecessary gaps without artificially forcing every card to the same height.

At the same time, a wider, featured card spanning two columns should align its own inner elements, such as title, meta line and call-to-action button, to exactly the same column lines the rest of the single-column cards use. That is exactly what subgrid is for: it ties a nested grid structure to the track grid of the outer grid, instead of opening its own, independent coordinate system.

2. Subgrid in brief: tying nested grids to the parent's track grid

Normally every nested display: grid element opens its own, independent coordinate system of columns and rows, unrelated to the track grid of the surrounding grid. The subgrid value for grid-template-columns or grid-template-rows fundamentally changes that: a grid item that itself spans several tracks of the parent grid can adopt those tracks directly, instead of defining its own, potentially different track sizes.

The result is precise alignment across component boundaries, something that previously could only be approximated with manually synchronized, hardcoded width values or CSS custom properties. For cards, forms, or table rows that need to align internally with the same grid as their surroundings, subgrid is now broadly supported and production-ready.

3. Masonry layout in brief: grid-template-rows: masonry

The experimental masonry layout is activated with grid-template-rows: masonry and tells the browser to no longer compute the row axis of a grid using the classic grid algorithm with equal-height row tracks, but instead to place every item into whichever column currently has the least occupied space, similar to how JavaScript libraries have manually implemented Pinterest-style layouts for years.

An often-overlooked property of the specification matters here: masonry only changes the axis it is applied to, in this case rows. The column axis remains a completely regular, explicit track grid, defined as usual through grid-template-columns. This exact property is the key that makes combining masonry and subgrid meaningful at all.

4. The key insight: masonry only affects one axis, subgrid can use the other

Because a masonry grid with grid-template-rows: masonry keeps its column axis unchanged as a regular, explicit track grid, a child element spanning several of those columns can set its own grid-template-columns: subgrid and inherit the column lines directly from the parent grid. The row axis, by contrast, stays unsuitable for subgrid, because masonry does not generate fixed, addressable tracks there, but applies a dynamic packing logic instead.

In practice this means subgrid works within a masonry context exclusively for column alignment of elements that span multiple columns, never for row alignment. This limitation is not a bug but follows directly from how masonry works, and should be factored into the layout design from the start rather than surfacing later as a surprise.

5. Concrete example: a featured card with subgrid columns inside a masonry grid

The following example shows a four-column masonry grid where a featured card spans two columns. This card uses grid-template-columns: subgrid to align its internal breakdown of image, title and call-to-action exactly to the two spanned columns of the outer grid, instead of computing its own, independent two-column split.

Because the outer grid's row axis is dynamically packed by masonry, the card gets its own height internally through a regular grid-template-rows, independent of the parent grid. Only the column alignment is inherited, the height stays a component's own concern and adapts to the actual card content.


.card-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
  gap: 1.5rem;
}

.card--featured {
  grid-column: span 2;
  display: grid;
  grid-template-columns: subgrid;   /* inherits the parent grid's 2 tracks */
  grid-template-rows: auto 1fr auto; /* own rows, independent of the masonry grid */
  gap: 1rem;
}

.card--featured .card-title {
  grid-column: 1 / -1;
}

.card--featured .card-meta {
  grid-column: 1;
}

.card--featured .card-cta {
  grid-column: 2;
  justify-self: end;
}

6. A full card grid with regular and subgrid cards

In a real project, most cards in a grid are simple, single-column elements that do not need subgrid, because they only ever occupy a single column track anyway. Subgrid is worth applying specifically to the minority of multi-column, featured cards, while the rest of the grid gets by entirely without any nested grid declaration.

This mixed architecture, a masonry grid as the base with a handful of subgrid cards for special cases, keeps the code manageable and ensures subgrid is only used where it actually adds value, namely for elements that span multiple tracks of the parent grid.


.card {
  /* regular card: no subgrid declaration needed */
  grid-column: span 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
  gap: 1.5rem;
  align-tracks: start; /* prevents vertical stretching within a masonry track */
}

7. Browser support reality: why the full combination rarely works today

Subgrid itself is now broadly available across all current versions of Chrome, Firefox and Safari and counts as production-ready. Masonry, by contrast, is far less mature: grid-template-rows: masonry is so far primarily implemented experimentally in Firefox, while other browser engines pursue an alternative approach called item-flow layout, which is neither syntactically nor conceptually identical.

This divergence means a true, spec-compliant combination of masonry and subgrid currently only realistically works in full in a single browser, while it gets either completely ignored or meets a different mechanism in every other. For production projects, that is a decisive difference from subgrid alone, which has long been broadly usable.

8. Fallback strategy: a regular grid without masonry as a solid baseline

The most reliable approach is to build the layout fundamentally with a regular, non-experimental grid where every card in the same row shares the same height, and to add masonry purely as a progressive enhancement behind a feature query. Subgrid keeps working normally within this fallback, independent of the masonry fallback, because it is not tied to the row axis, only to column alignment.

This strategy delivers a functional, if not perfectly space-efficient, result in every browser, while users of a browser with masonry support automatically get the more tightly packed, visually more dynamic layout. It matters not to hardcode heights in the fallback branch, but to keep working with auto tracks, so the transition between the two variants does not feel visually abrupt.


.card-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: auto;   /* solid baseline: cards in the same row share the height */
  gap: 1.5rem;
}

@supports (grid-template-rows: masonry) {
  .card-grid {
    grid-template-rows: masonry;
  }
}

9. Practical recommendation: when the combination already pays off today

For internal tools, prototypes, or projects with an audience clearly restricted to a single browser, for example an internal Firefox-based dashboard, the full combination of masonry and subgrid can already be used in production today. For publicly accessible websites with a mixed browser audience, the combination of a solid grid fallback with progressive masonry enhancement remains the more pragmatic route.

Subgrid for aligning the columns of featured cards can be used confidently in production right now regardless of whether masonry is even in play, because subgrid itself has long enjoyed broad support. Anyone looking to replace JavaScript masonry libraries with native solutions today should therefore consistently hide native masonry behind a feature query rather than shipping it as the only solution.

Layout strategy Packs uneven heights Inner alignment across cards Browser support
grid-template-rows: masonry + subgrid Yes, tightly packed Yes, through subgrid columns Experimental only, mainly Firefox
Regular grid with equal row height No, gaps from the tallest card Yes, through regular tracks Full, all current browsers
CSS multi-column (columns) Yes, similar masonry look No, no row alignment possible Full, all current browsers
Flexbox with flex-wrap No, row height follows the tallest card Partial, without a real track grid Full, all current browsers
JavaScript masonry library Yes, tightly packed Yes, with manual extra logic Full, but an extra JS bundle

Mironsoft

Modern CSS, layout architecture and rendering performance

CSS that stays maintainable instead of breaking with every change?

We review existing stylesheets for specificity chaos and layout thrashing, then build a CSS architecture with cascade layers, custom properties and modern layout primitives that still makes sense after the tenth feature.

CSS Audit

Systematically uncovering specificity issues, cascade conflicts and unused selectors.

Architecture Refactoring

Introducing cascade layers, custom properties and design tokens cleanly.

Performance Tuning

Fixing layout thrashing, expensive selectors and rendering bottlenecks.

10. Summary

Combining Subgrid and Masonry: The Essentials at a Glance

Core idea

Masonry only changes one axis (usually rows), the other axis stays a regular track grid that subgrid can still use.

Subgrid's role

grid-template-columns: subgrid aligns multi-column, featured cards exactly to the columns of the masonry grid.

Support reality

Subgrid is broadly supported, masonry is currently mainly experimental in Firefox, other engines pursue a different approach.

Fallback strategy

Regular grid as the baseline, masonry added as a progressive enhancement through @supports(grid-template-rows: masonry).

11. FAQ: Combining Subgrid and Masonry: The Essentials at a Glance

1Can I use subgrid directly on the row axis of a masonry grid?
No. Masonry replaces the row axis with a dynamic packing logic without fixed, addressable tracks, so subgrid would have nothing to inherit there. Subgrid only works in this context on the unchanged column axis.
2Why does the column axis stay unchanged with grid-template-rows: masonry?
Because the masonry value only affects the axis it is applied to. The other axis keeps its regular, explicit track grid from grid-template-columns.
3What is subgrid specifically useful for in a masonry grid?
Mainly for multi-column, featured cards whose inner elements like title, meta line and button should align exactly to the same column lines as the rest of the cards.
4Do all browsers support the combination of masonry and subgrid?
No. Subgrid is broadly supported, masonry through grid-template-rows: masonry is currently mainly implemented experimentally in Firefox. Other engines pursue their own, different approach called item-flow layout.
5How do I build a safe fallback for browsers without masonry support?
With a regular grid as the baseline where every card in a row shares the same height, plus an @supports(grid-template-rows: masonry) query that only activates masonry where the browser understands it.
6Does subgrid work the same way in the fallback grid as in the masonry grid?
Yes, because subgrid works independently of whether the parent grid's row axis is regular or packed by masonry. Only column alignment is inherited, regardless of row behavior.
7Is CSS multi-column a good alternative to masonry?
Visually similar, but without real row alignment between columns, which makes subgrid for inner elements impossible. For a pure packing look without alignment needs, multi-column is still a robust, broadly supported option.
8Should I replace JavaScript masonry libraries right now?
Not fully yet for projects with a broad browser audience, as long as native masonry support stays limited to a single browser. A fallback grid with progressive enhancement is the more pragmatic intermediate step.
9Can a featured card span multiple rows instead of columns?
Yes, but then it cannot use subgrid for the row axis as long as that axis is controlled by masonry. Such a card's height still has to be managed through its own, independent grid-template-rows definition.
10How do I test whether a browser supports masonry?
With the feature query @supports(grid-template-rows: masonry) in CSS, or programmatically with CSS.supports('grid-template-rows', 'masonry') in JavaScript if the information is needed at runtime.