Masonry Grid

A responsive masonry layout for items of different heights.

Examples

Images

The default layout uses CSS columns: no JavaScript places the items, and they read down each column. revealOnView lets each item rise into place once, the first time it comes into view.

Harbour at noon
Harbour at noon
Meadow road
Meadow road
North ridge
North ridge
Low valley
Low valley
Hills after rain
Hills after rain
Dunes at dusk
Dunes at dusk
Night camp
Night camp
Morning shore
Morning shore
The bay again
The bay again

Mixed cards

layout='balanced' keeps the reading order from left to right: each item goes to the bottom of the shortest column. Use it when the order matters, as in a feed.

Day 3, the north ridge
Day 3, the north ridge
Plan for Saturday

Leave the harbour at 08:30, lunch at the ridge hut, and walk down before the light goes. The last ferry is at 20:10.

ILInes LaurentJoined the trip
Packing
  • Two warm layers
  • Ferry tickets
  • Long lens
  • Headlamp
Day 4, the dunes
Day 4, the dunes
Saturday, 17 degreesClear sky, light wind from the west
TRTomas ReyesBooked the lake house
Day 5, night camp
Day 5, night camp
Shared costs1,240Split between 4 people

Installation

npx shadcn@latest add https://ui.ndekocode.dev/r/motion-masonry-grid.json

Component API

MasonryGrid

PropTypeDefaultDescription
childrenReactNodeThe items, each with a key.
layout'columns' | 'balanced''columns'CSS columns read down each column; balanced keeps the order across the columns.
columnWidthnumber220The narrowest a column may get, in pixels. It sets how many columns fit.
maxColumnsnumber4The most columns, however wide the grid.
gapnumber16The space between columns and between items, in pixels.
revealOnViewbooleanfalseEach item fades and rises 12px in 320ms, once, when it first comes into view.
classNamestringClasses of the grid.

The entrance is off by default: inside an application, content should not wait for the scroll to appear. Turn it on for marketing pages. Under reduced motion the items are always shown as they are. Items of the same row enter 40ms apart in the balanced layout.

The balanced layout measures the items once they are rendered, before the browser paints, and again when the number of columns changes. Give images a fixed aspect ratio so their height is known before they load.