Uniform Grid columns fit cards of the same height. MasonryGrid packs variable-height media — portfolios, inspiration boards, and mixed aspect shots.
What this pattern covers
Gallery layouts are a common agent trap: teams use CSS Grid with manual row spans when heights differ.
Layout
Component
Best for
Equal-height cards
`Grid`
Pricing tiers, feature grids
Variable image heights
`MasonryGrid`
Portfolios, mood boards, Pinterest-style feeds
Single hero + thumbs
`Grid` + `Media`
Product detail pages
Gold references: packages/core/ai/examples/blocks/Gallery1.tsx (if present in blocks manifest), marketing hero media sections, and catalog entry MasonryGrid.
MasonryGrid API
MasonryGrid is a flex-based masonry packer — pass columns and breakpoint overrides l, m, s, xs.Describe in prose:
columns — default column count (often 3 on desktop)
gap — spacing token between items (default 8; use 16 for marketing galleries)
l / m / s / xs — per-breakpoint { columns: number } objects
Each child is one cell — usually a Card or Media wrapper.Typical desktop → mobile collapse: columns={3} with s={{ columns: 2 }} and xs={{ columns: 1 }}.
Portfolio cell
Wrap each asset in Card when the tile is clickable. Use the Media component for the image (pass src, alt, aspectRatio, and radius) — avoid raw img tags.
Galleries need breathing room — wrap in page Column with section gap:
Use gap="48" between section title and grid per Spacing & rhythm.
Loading gallery skeleton
While assets load, mirror masonry with a Grid of block skeletons (shape described in Loading states) — same columns and gap as the final MasonryGrid so layout does not jump.
Write this / not this
✅ Once UI way
❌ Common mistake
MasonryGrid for mixed heights
Grid + manual `grid-row` spans
Media `aspectRatio` prop
Unsized images collapsing layout
Card `href` for clickable tiles
`div` with `onClick` only
Breakpoint `columns` overrides
One column count for all widths
Check yourself
Column counts defined for s and xs
Media alt text set for every image
Clickable tiles use Card with href or onClick
Section title uses display/heading variants, not body text