CSS Grid Lanes: Masonry Layout Without JavaScript

Pinterest-style layouts without a JavaScript library

Uneven cards and images used to mean Masonry.js measuring every item, or CSS columns that read top to bottom. display: grid-lanes packs each item into the shortest lane in CSS.

Old wayMasonry.js
import Masonry from 'masonry-layout';new Masonry('.gallery', {  itemSelector: '.item',  columnWidth: 250,  gutter: 16});
5 lines
.gallery  {  display: grid;  display: grid-lanes;   grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));  gap: 16px;}/* no Masonry.js, no column-count */
Limited availability11% global usage

This feature is not Baseline because it does not work in some of the most widely-used browsers.

Not ready for production without a fallback.

26.4+

Only Safari 26.4 and iOS Safari 26.4 ship display: grid-lanes on by default. Chrome, Edge, and Firefox have implementations behind a flag. A display: grid declaration above display: grid-lanes keeps a regular grid in browsers that ignore the new value.

mixed-height items pack into the shortest column
display: grid-lanes

The browser packs the lanes

Each item goes into whichever column (or row) has the most room. No measuring, no resize observers, no relayout after images load.

Source order stays left to right

CSS columns fill top to bottom, so tab order jumps down a column. Grid lanes keep document order across the row, then pack vertically.

Still CSS Grid

gap, span, line-based placement, and repeat(auto-fill, minmax()) all work. Define columns for a waterfall, or rows for a brick layout.

Old Approach
Masonry.js
or column-count
Modern Approach
display: grid-lanes
CSS Grid Level 3

How it works

Variable-height galleries left a choice between a JavaScript library and a CSS hack. Masonry.js measured every item and assigned a column. CSS column-count packed the visual gaps, but reading and tab order ran down each column first. Regular CSS Grid kept left-to-right order and left holes under short items.

display: grid-lanes keeps one axis as a normal grid and packs the other. grid-template-columns makes a waterfall: items drop into the shortest column. grid-template-rows makes a brick wall: items slide into the shortest row. Browsers that do not recognize grid-lanes drop that declaration, so a display: grid line above it keeps a regular grid as the fallback.

The earlier prototypes, display: masonry and grid-template-rows: masonry, are no longer the spec. flow-tolerance (default 1em) treats near-equal lane lengths as a tie so visual order stays closer to source order. Safari 26.4 ships this unflagged. Chrome, Edge, and Firefox still hide it behind a flag.

ESC