Masonry

A no-JavaScript waterfall layout with a multi-column baseline and progressive Grid Lanes enhancement.

A real waterfall in every browser

The multi-column baseline packs unequal articles today; supporting browsers enhance the same markup with Grid Lanes.

Quick note

Two useful lines.

Case study

Fewer layout queries

A minimum column width lets the collection adapt inside any container, including this resizable preview.

Quote
Good defaults make the simple path dependable.
API

One gap

The same value spaces columns and stacked items.

Tiny
Progressive

Grid Lanes ready

When native shortest-lane placement arrives, this markup upgrades without a rewrite.

Semantic content

Articles remain articles.

More examples

Each example introduces a different part of the shipped API.

Source order remains the reading order

Numbering exposes the fallback's down-then-across flow while keeping the DOM and keyboard sequence authoritative.

1 · First
2 · Second, with enough supporting copy to become taller
3 · Third
4 · Fourth, with a second line
5 · Fifth
6 · Sixth and final

Cap columns without losing responsiveness

columns sets a maximum while column-width still lets the layout reduce its count as the preview narrows.

Maximum three columns
This card is taller because it explains the responsive cap in a little more detail.
Resize the right edge
No media query
One column when needed

Theme the layout through component tokens

Hierarchical variables provide a reusable recipe while attributes remain available for one-off instances.

Compact
A denser gallery recipe with a smaller shared gap
Token first
Still responsive
Customizable

Overview

Masonry should still look like masonry in an ordinary browser. CSS Tags uses multi-column layout as the dependable baseline, so unequal items pack into a waterfall today. Browsers that support the current CSS Grid Level 3 draft upgrade the same markup to display: grid-lanes, which places each new item in the shortest available lane.

The two algorithms have different visual ordering: the baseline flows down each column before moving across, while Grid Lanes can select the shortest lane. The DOM order remains the semantic and keyboard order in both cases.

Live-safe markup

The same component API works as a custom element, data host, or class host:

<masonry-layout column-width="14rem" gap="1rem">
<article>Short card</article>
<article>Card with more content...</article>
<article>Another card</article>
</masonry-layout>
<section data-masonry column-width="14rem" gap="1rem">...</section>
<section class="masonry-layout" column-width="14rem" gap="1rem">...</section>

Use column-width as the responsive minimum width and columns as an optional maximum count. gap controls both the column gap and the space below each item. No script or fixed container height is required.

API

InputPurposeDefault
column-width / --masonry-column-widthResponsive fallback column width14rem
columns / --masonry-columnsMaximum fallback column countauto
gap / --masonry-gapHorizontal and vertical item spacingvar(--space-md)
fill / --masonry-fillMulti-column balancing (balance or auto)balance
cols / --masonry-tracksGrid Lanes column tracksresponsive 14rem tracks
rows / --masonry-rowsGrid Lanes row tracksnone
flow-tolerance / --masonry-flow-toleranceGrid Lanes placement tolerancenormal

tolerance remains as a backwards-compatible alias for flow-tolerance. Child col and row attributes apply to track placement when Grid Lanes is available.

How progressive enhancement works

:is(masonry-layout, [data-masonry], .masonry-layout) {
display: block;
column-width: var(--masonry-column-width, 14rem);
column-gap: var(--masonry-gap, 1rem);
}
:is(masonry-layout, [data-masonry], .masonry-layout) > * {
inline-size: 100%;
margin-block-end: var(--masonry-gap, 1rem);
break-inside: avoid;
}
@supports (display: grid-lanes) {
:is(masonry-layout, [data-masonry], .masonry-layout) {
display: grid-lanes;
grid-template-columns: var(--masonry-tracks);
gap: var(--masonry-gap);
flow-tolerance: var(--masonry-flow-tolerance);
}
}

The custom mixin in components/masonry.css follows the same baseline and enhancement model. It is forward-looking syntax, not a production dependency.

Accessibility

Keep the DOM in a logical reading and keyboard-navigation order, use semantic children, and give images meaningful alt text. Avoid using masonry for steps, rankings, or other content whose meaning depends on a strict visual sequence.