CSS Masonry in 2026: display: grid-lanes and Browser Support
Quick answer: Native CSS masonry is now called Grid Lanes and is written display: grid-lanes, with lanes defined by grid-template-columns. Safari 26.4 shipped it on macOS and iOS on March 24, 2026. As of October 2, 2026, Chrome and Edge (140+) and Firefox still keep it behind a flag, so roughly one visitor in ten gets it. Ship CSS columns or a small JavaScript placement as the default and upgrade inside @supports (display: grid-lanes).
Masonry is the layout people have asked CSS for since Pinterest made it famous: items of different heights packed into columns, each new item dropping into whichever column is currently shortest. It took nine years of proposals, two competing syntaxes and a public naming survey to settle. The result is settled now, it is in one stable browser, and most of what you will read about its support is out of date in one direction or the other.
The correction: Safari did ship it, and Firefox did not
Two opposite mistakes are circulating. The first says no browser has shipped masonry and that reports of Safari 26.4 support were wrong. They were right. WebKit’s Safari 26.4 feature announcement, published March 24, 2026, says “Safari 26.4 adds support for Grid Lanes” and that “this capability is available in CSS with display: grid-lanes,” including the flow-tolerance property. Can I Use and MDN’s compatibility data both record Safari and Safari on iOS 26.4 as supported, and Safari 27.0 added Grid-Lanes badges to Web Inspector in September.
The second mistake says Firefox 155 and later implement masonry through grid-template-columns: masonry. Firefox has carried an implementation of the older grid-template-*: masonry syntax since Firefox 77 in 2020, but only behind the layout.css.grid-template-masonry-value.enabled preference. Can I Use lists it as disabled by default in every Firefox version through 160, and MDN’s data has display: grid-lanes as unsupported in Firefox. Firefox 155 (September 1, 2026) changed nothing here. Writing grid-template-columns: masonry in production does nothing for Firefox users and nothing for anyone else either.
Browser support as of October 2, 2026
| Browser | display: grid-lanes | Notes |
|---|---|---|
| Safari, macOS and iOS | Shipped in 26.4 | March 24, 2026, with flow-tolerance. Earlier versions back to 16.4 had masonry behind a feature flag. |
| Chrome | Flag only | Behind the CSS Grid Lanes Layout flag since 140. No shipping milestone set. |
| Edge | Flag only | Same Chromium flag. Microsoft engineers lead the Chromium implementation. |
| Firefox | Flag only | Older grid-template-*: masonry syntax behind a preference since 77. Needs updating to grid-lanes. |
| Samsung Internet, Opera | No | Will follow Chromium. |
Can I Use puts global support at about 11%, almost all of it Safari. The Chrome Platform Status entry lists dense packing, reverse placement, subgrid and fragmentation among the gaps still open in Chromium’s version. WebKit’s own “when will Grid Lanes arrive” post from January 2026 said the same about the other engines: they are working on it, with no date.
How the syntax got here
If you have code from an older tutorial, this is why it does not work:
- 2020: the first draft extends Grid with a
masonrykeyword, writtengrid-template-rows: masonryfor a column waterfall. Firefox 77 implements it behind a flag. Safari Technology Preview adds the same syntax in 2023. - 2024: the Chrome team proposes a separate layout mode,
display: masonry, with its own track properties, arguing that masonry should not overload Grid. WebKit argues the opposite and asks developers to weigh in. - January 31, 2025: the CSS Working Group resolves to reuse Grid’s templating and placement properties, so
grid-template-columns,gapandgrid-columnkeep working. - November 2025: after a survey with more than 300 responses, the group resolves that “masonry switch will be
display: grid-lanes.” - January 7, 2026: the tolerance property, briefly called
item-tolerance, is renamedflow-tolerance. - March 24, 2026: Safari 26.4 ships the finished core syntax.
So grid-template-rows: masonry and display: masonry are both dead syntaxes. Neither will ever ship in a stable browser. The specification now lives in CSS Grid Layout Level 3.
The grid-lanes syntax
.gallery {
display: grid-lanes;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 16px;
}
That is a complete Pinterest layout. Items keep their natural height and each one goes into the lane that is currently shortest. You define lanes along one axis only:
- Set
grid-template-columnsand you get vertical lanes, the waterfall. This is the default: the spec says that unless columns arenoneand rows are set, the inline axis is the grid axis. - Set only
grid-template-rowsand you get horizontal lanes, the brick wall that photo sites use for rows of mixed-width images. grid-column: span 2works, so a featured item can cover two lanes. You can also pin an item to a lane withgrid-column: 1.flow-tolerance(initial valuenormal, which resolves to1em) treats lanes within that distance of each other as tied, so an item goes to the earlier lane instead of jumping across the page for a two-pixel advantage. Raise it to keep the order more row-like.infiniteis also valid.
Live demo: native, JavaScript or columns
Which masonry path is your browser on?
The demo picks native Grid Lanes when CSS.supports('display', 'grid-lanes') is true and the JavaScript fallback otherwise. Switch paths and watch the numbers: they are the DOM order.
Checking your browser…
Applied CSS
Compare the JS fallback with CSS columns. Both look like masonry, but in columns item 2 sits under item 1 rather than beside it, because multi-column layout fills each column top to bottom before moving right. Grid Lanes and the JS placement both go across, which is what a reader scanning a feed expects.
What to ship today
With nine in ten visitors on a browser without Grid Lanes, the fallback is the real layout for most people. Pick it on purpose.
| Approach | Visual order | Gaps | JavaScript | Good for |
|---|---|---|---|---|
| CSS columns | Down each column | None | None | Unordered galleries, quotes, testimonials |
Grid with dense and spans | Mostly across, reordered to fill holes | Some, unless every height is a multiple of the row | None | Cards with a few known size classes |
| Grid plus JS placement | Across, true masonry | None | ~25 lines, reruns on resize | Feeds and anything where order matters |
| Masonry library | Across | None | A dependency, absolute positioning | Legacy code you are not touching yet |
CSS columns
.gallery {
columns: 220px; /* as many 220px+ columns as fit */
column-gap: 16px;
}
.gallery > * {
break-inside: avoid; /* keep each card in one piece */
margin-bottom: 16px;
}
Zero JavaScript and works everywhere. The cost is order: item 2 is below item 1, and adding items later reshuffles every column. Fine for a photo gallery, wrong for a chronological feed.
Grid with dense packing
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
grid-auto-rows: 120px;
grid-auto-flow: dense;
gap: 16px;
}
.tall { grid-row: span 2; }
.wide { grid-column: span 2; }
This is the “bento” look rather than masonry. Items snap to row multiples, and dense backfills holes by pulling later items forward, which breaks the match between visual and DOM order. It works when you control the content and can assign a size class to each card. For the trade-offs between the two layout modes in general, see Flexbox vs Grid.
A small JavaScript fallback
This is the code the demo runs. It keeps the element a normal grid, sets 1px rows, and places each item explicitly in the shortest column. The container’s height stays automatic, so nothing is absolutely positioned and the page flows normally around it.
function placeLanes(grid) {
const cs = getComputedStyle(grid);
const lanes = cs.gridTemplateColumns.split(' ').length;
const gap = parseFloat(cs.columnGap) || 0;
const filled = new Array(lanes).fill(0);
for (const item of grid.children) {
item.style.gridRow = item.style.gridColumn = '';
item.style.alignSelf = 'start';
const h = Math.ceil(item.getBoundingClientRect().height);
let lane = 0;
for (let i = 1; i < lanes; i++) {
if (filled[i] < filled[lane] - 16) lane = i; // 16px ≈ flow-tolerance: 1em
}
item.style.gridColumn = lane + 1;
item.style.gridRow = (filled[lane] + 1) + ' / span ' + h;
filled[lane] += h + gap;
}
}
/* .gallery { display: grid; grid-auto-rows: 1px; row-gap: 0; ... } */
if (!CSS.supports('display', 'grid-lanes')) {
const grid = document.querySelector('.gallery');
let lastWidth = 0;
new ResizeObserver(([entry]) => {
if (entry.contentRect.width !== lastWidth) {
lastWidth = entry.contentRect.width;
placeLanes(grid);
}
}).observe(grid);
}
Two details matter. Rerun it when images load, or give every <img> its width and height attributes so the height is known before the file arrives. And only rerun on width changes, because placement changes the grid’s height and a naive observer will loop.
Progressive enhancement with @supports
Write the fallback as the default and put Grid Lanes inside a feature query. Browsers without support skip the block entirely:
.gallery {
columns: 220px;
column-gap: 16px;
}
.gallery > * { break-inside: avoid; margin-bottom: 16px; }
@supports (display: grid-lanes) {
.gallery {
display: grid-lanes;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 16px;
columns: auto; /* undo the fallback */
}
.gallery > * { margin-bottom: 0; }
}
If your fallback is a plain grid, the shortest version relies on the cascade dropping values it does not understand:
.gallery {
display: grid; /* everyone */
display: grid-lanes; /* overrides it where supported */
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 16px;
}
Keep the JavaScript behind CSS.supports('display', 'grid-lanes') as in the snippet above, so Safari users never download or run it. Someone who turns on the Chrome flag will also pass the check and get the native path, which is what you want.
Found a masonry layout you want to study? Working out whether a site uses columns, a library or grid-lanes means clicking through nested wrappers in DevTools. CSS DNA, a browser extension for inspecting CSS, copies any element’s CSS in one click, free, so you can read the container’s display and track definitions straight away. Add CSS DNA to Chrome (free).
Order, focus and accessibility
Every masonry approach moves items away from where the DOM puts them. Keyboard focus and screen readers follow the DOM, so in a waterfall a Tab press can jump from the bottom of one column to the top of the next. The Grid Level 3 spec addresses this directly and asks authors to “design layouts where such backtracking is minimized so that focus and reading order can be more easily followed.” In practice:
- Keep heights within a reasonable range. One very tall item causes most of the backtracking.
- Raise
flow-tolerancewhen order matters. A larger value keeps items in row order more often, at the cost of slightly less even column heights. - Prefer columns-based fallbacks only where order genuinely does not matter, since they are the most out of step with reading order.
How to check and debug
- Which path is live? Run
CSS.supports('display', 'grid-lanes')in the console. In Safari 26.4+ it returnstrue. Everywhere else, unless a flag is on, it returnsfalse. - Inspect in Safari. Web Inspector’s Grid overlay supports Grid Lanes as of 26.4, with numbered overlays showing placement order, and Safari 27 adds a Grid-Lanes badge in the Elements tab.
- Everything is in one column.
grid-template-columnsis missing or resolves to a single track. Without a column template there is nothing to divide the container into lanes. - Old syntax in your CSS. Search for
masonry.grid-template-rows: masonryis not supported by any stable browser, so the declaration is dropped and you get an ordinary grid with gaps under the short items. - The JS fallback leaves gaps. Heights were measured before images loaded. Add dimensions to images or rerun placement on each image’s
loadevent. - Testing in Chrome. Turn on the flag at
about://flags(search “CSS Grid Lanes Layout”). Chromium’s implementation is still incomplete, so test real behaviour in Safari.
Grid Lanes sits next to the other new layout and paint features we track in Modern CSS in 2026. Its mirror image this year is CSS corner-shape, which shipped in Chromium first and is still waiting on Safari.
Frequently asked questions
Can I make a masonry layout with only CSS?
Yes, in two ways. display: grid-lanes gives true masonry in Safari 26.4 and later. Everywhere else, CSS multi-column layout (columns: 220px with break-inside: avoid) produces the same look without JavaScript, but items flow down each column instead of across, so it suits galleries where order does not matter.
Which browsers support CSS masonry?
As of October 2, 2026, only Safari 26.4 and later, on macOS and iOS, supports display: grid-lanes without a flag. It shipped March 24, 2026. Chrome and Edge 140+ have it behind the CSS Grid Lanes Layout flag, and Firefox has an older grid-template-*: masonry implementation behind a preference. Can I Use puts global support near 11%.
Does grid-template-rows: masonry still work?
No. It was the original 2020 syntax and only ever worked behind flags, in Firefox and earlier Safari Technology Preview builds. The CSS Working Group replaced it with display: grid-lanes in November 2025, and Safari 26.4 ships only the new syntax. Search your stylesheets for masonry and replace it.
What happened to display: masonry?
It was Chrome’s 2024 proposal for a separate masonry layout mode. The working group chose to build on Grid’s properties instead, and in November 2025 picked the name grid-lanes after a public survey. Chromium’s flagged implementation is being updated to the final syntax, so display: masonry will not ship.
What is flow-tolerance?
flow-tolerance sets how much shorter a lane must be before an item skips ahead to it. The initial value normal resolves to 1em; lanes within that distance count as tied and the earlier lane wins. Larger values keep items closer to reading order. It was called item-tolerance until a January 7, 2026 rename.
Read any site’s layout in one click
Copy an element’s CSS, sample colors, and see a site’s palette and fonts as a design-system preview. It runs on-device.
Add CSS DNA to Chrome (free)Free: element CSS, eyedropper, ranked palette. Pro, $5/mo after a 7-day trial: exports, DESIGN.md, CSS audit. No account.