Seven ways to build masonry: CSS columns, a grid with row spans, native masonry with a columns fallback, a pin board of image cards, justified photo rows, a wall of quotes of different lengths and a grid masonry with a featured tile spanning two columns.
The simplest masonry: column-width makes as many columns as fit, items flow down each column and break-inside: avoid stops a card being split. Reading order runs down the first column then the next, which suits galleries better than ranked lists.
A grid with small, fixed row tracks where each item spans a number of rows matching its height, plus grid-auto-flow: dense to backfill gaps. Unlike columns, items read left to right, row by row, which keeps their order meaningful.
Browsers that support grid-template-rows: masonry get true masonry from one line, with items placed in order into the shortest column. Everywhere else, @supports falls back to CSS columns, so the layout never breaks while the standard settles.
Pinterest-style cards of different heights, each with an image area and a caption, flowing in CSS columns. The images keep their own aspect ratios, which is what makes the board look natural, and the captions stay attached because cards never split.
The horizontal cousin of masonry: rows of equal height where items of different widths stretch to fill each row exactly, like a photo library. Each item's flex-grow is its aspect ratio, so wide images claim more of the row.
Quotes of very different lengths look best in masonry, because a regular grid would leave big gaps under the short ones. CSS columns pack them neatly, and each quote is a figure with its attribution so the wall is still a sensible list when read aloud.
View code
<div class="ms6"><figure><blockquote>Fast.</blockquote><figcaption>Ola</figcaption></figure><figure><blockquote>The team rebuilt our checkout in a week and our mobile sales went up the month after.</blockquote><figcaption>Priya, Brew Lab</figcaption></figure><figure><blockquote>Clear pricing and no surprises.</blockquote><figcaption>Jonas</figcaption></figure><figure><blockquote>They explained every decision, which made the whole project easier to approve internally.</blockquote><figcaption>Dana, Northwind</figcaption></figure></div>
A grid-based masonry where the first item spans two columns as a featured tile, something CSS columns cannot do. Row spans set the heights, and dense packing fills the spaces around the big tile.
column-width with break-inside: avoid on items is the easiest masonry. Items flow down the first column before the next, so it suits galleries but not lists where order matters.
Grid spans: row order
With small grid-auto-rows and each item spanning rows to match its height, items read left to right. Add grid-auto-flow: dense to backfill gaps, knowing it can move items out of source order.
Native masonry is coming
grid-template-rows: masonry places items into the shortest column in source order with one line. Use it inside @supports with columns as the fallback until support is broad.
Keep source order sensible
Keyboard and screen reader users follow the HTML order, not the visual one. Put the most important items first in the markup whichever technique you choose.
Frequently asked questions
Do I need a JavaScript masonry library?
Rarely now. CSS columns or grid spans cover most cases, and native masonry is arriving.
How do I know the row span for each item?
For fixed content you can set it by hand; for images, calculate it from the image's aspect ratio.
What is a justified layout?
Rows of equal height whose items stretch to fill each row, like photo libraries. Flex-grow based on aspect ratio does it.