← Read

Design · · 6 min read

Masonry finally shipped in CSS. It is called grid lanes

Safari ships display: grid-lanes, the CSS Working Group's answer to masonry. The syntax, the flow-tolerance property, and the reading-order trap.

The Pinterest-style layout — columns of uneven cards, each new card dropped into the shortest column — is now a CSS layout mode. It is not called masonry:

.gallery {
  display: grid;
  display: grid-lanes;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 1rem;
}

That is the whole layout. No measuring, no absolute positioning, no library.

The catch is support. At the time of writing, display: grid-lanes ships in Safari 26.4 and later, including on iOS, and in no other engine: MDN's browser compatibility data records false for Chrome and Firefox. So this is a progressive enhancement today, not a replacement for your JavaScript masonry.

This article covers what the spec defines, the one property you have never heard of, and the accessibility problem the spec itself warns about.

Why it isn't called masonry

If your searches keep returning display: masonry, that is the old name. The proposal has been renamed more than once on its way through the CSS Working Group, and the current names come from CSS Grid Layout Module Level 3.

You may have readCurrent name
display: masonrydisplay: grid-lanes (and inline-grid-lanes)
item-toleranceflow-tolerance
the item-* family of flow propertiesdropped

The spec's own change log records the rename of item-tolerance to flow-tolerance, and the dropping of "the item-* proposal for unified flow controls across layout modes". Level 3 lists its additions since Level 2 as grid lanes layout, the flow-tolerance property, and an expansion of repeat(auto-fill) and repeat(auto-fit) to accept indefinite track sizing functions.

The spec's term for the layout is worth knowing, because it explains the behaviour. A grid lanes container lays items out "into pre-defined tracks similar to grid layout in one axis (called the grid axis), but flows them freely similar to flex layout in the other (called the stacking axis)".

Columns or rows: the template decides

There is no direction property to set. The orientation comes from which template you declare:

  • Set grid-template-columns and you get a waterfall that grows downward.
  • Set only grid-template-rows (leaving grid-template-columns: none) and you get a brick wall that grows sideways.
/* Waterfall */
.a { display: grid-lanes; grid-template-columns: 100px 200px; }

/* Brick wall */
.b { display: grid-lanes; grid-template-rows: 100px 200px; }

In the grid axis you keep the full power of grid: track sizes, line names, areas, and grid-column / grid-row placement all work as they do in a normal grid container. Subgrid works too, but only in the grid axis. In the stacking axis there is no grid — which is why absolutely positioned children only get two lines to work with there, the start and end edges of the stacking range.

The spec still carries an open issue about whether grid-auto-flow is the right property for this or whether a separate grid-lanes-direction should be defined, so treat the orientation mechanism as the least settled part.

flow-tolerance, the property nobody mentions

Items go into whichever track is least filled. That rule alone produces a layout that reads badly: two columns differing by three pixels are not perceived as different, but the algorithm still picks the shorter one, so items appear to jump backwards.

flow-tolerance sets the threshold at which two tracks count as the same height:

.gallery {
  display: grid-lanes;
  flow-tolerance: 2em;   /* normal | <length-percentage> | infinite */
}
A grid lanes container with four columns filled to different heights, where the fourth column is shortest but the first is only slightly taller, so the tolerance value decides which column receives the next item.
Image: W3C CSS Working Group, CSS Grid Layout Module Level 3

The initial value is normal, which resolves to 1em in grid lanes layout and 0 everywhere else. Percentages are relative to the grid-axis content box of the container. It is not inherited, and it animates as a length.

infinite makes items fill strictly in source order, ignoring track lengths entirely. The spec discourages reaching for it: it "can result in consecutive items being placed in dramatically different positions in the stacking axis, which can be confusing to readers", and suggests that if 1em is too small you try a larger length such as 10em or 50vh instead.

A practical starting point: leave it alone for image galleries where the cards are all roughly one shape, and raise it to a couple of em for text cards, where small height differences are invisible but out-of-order placement is not.

The reading-order trap

This is the part that most write-ups skip, and it is the reason to design the layout rather than just switch it on.

Auto-placement generally moves forwards, but mixing spanning items or explicitly placed items with auto-placed ones makes it backtrack. The spec's own example: seven items in a five-column container, where item 4 spans three columns and does not fit in the space left on the first line. It drops to the first column — "the highest available space into which it will fit" — and the single-column items after it then lay out above it, "violating the natural reading order".

A grid lanes layout where items 1, 2, 3, 5 and 6 occupy the first row, item 4 spans three columns below item 3, and item 7 sits under item 5 — so the visual order no longer matches the DOM order.
Image: W3C CSS Working Group, CSS Grid Layout Module Level 3

Tab order and screen-reader order follow the DOM, so a reader moving through the page visually and a reader moving through it by keyboard now disagree.

The spec's advice, in order of preference:

  1. Design so backtracking is minimal: avoid combining mixed span sizes in the grid axis with very different item sizes in the stacking axis, and use explicit placement to group related items rather than to disrupt their order.
  2. Tune flow-tolerance to a value "large enough to avoid gratuitous differentiation among similarly-sized tracks, but not so large that meaningful differences get ignored".
  3. If the items genuinely have no inherent order, use the reading-flow property so the browser can re-order them for reading and linear navigation. See how reading-flow works for what it can and can't fix.

Shipping it now

The fallback is two declarations, and it is in the spec as the graceful-degradation example:

.gallery {
  display: grid;
  display: grid-lanes;  /* ignored where grid lanes is not supported */
  grid-template-columns: 150px 100px 50px;
}

An engine that has never heard of grid-lanes discards the second declaration and renders a plain grid with the same tracks. You get a tidier, gappier layout instead of a broken one — no @supports block needed, though @supports (display: grid-lanes) works if you want to change other properties at the same time.

For debugging, Safari's Web Inspector knows about the layout mode. The Safari 27 release notes record that it "added Subgrid and Grid-Lanes badges to the Elements tab for easier identification of subgrid and grid-lanes layout contexts".

The honest summary: use it as an enhancement on a design that already works as a grid, and keep your JavaScript masonry only if the gappy grid fallback is genuinely unacceptable. Browser support is time-sensitive — check it again before you rely on it.

FAQ

Is CSS grid lanes Baseline yet?

No. Baseline requires support in all core browsers, and at the time of writing only Safari ships it. Feature data marks masonry as not Baseline.

Can I keep using display: masonry?

The spec now defines grid-lanes and inline-grid-lanes as the inner display types that establish this layout, and MDN's compatibility data records no shipping support for a masonry value of display. Anything you read about display: masonry describes an earlier revision of the same proposal.

Does order work in a grid lanes container?

Yes. The spec says all CSS properties work the same as in a regular grid container unless stated otherwise, and gives order as the example. The usual caution applies: order changes layout order, not reading order.

What does grid-auto-flow: dense do here?

It allows the placement algorithm to backtrack into earlier empty slots, as it does in grid. Because placement and sizing are intertwined in grid lanes layout, an item only backtracks into a slot it actually fits, so the effect is smaller than in a normal grid.

Will Chrome and Firefox ship the same thing?

They are working from the same spec, but it is an Editor's Draft with open issues, including how the orientation is set. Write the fallback, and re-check support before removing it.

Sources

More to read