Native Pinterest layouts without JavaScript
Masonry layouts, grids in which items of varying height are stacked without gaps, have been a JavaScript problem for years. The CSS Masonry draft specification brings this behavior natively into the browser: grid-template-rows: masonry promises what previously only libraries such as Masonry.js or Isotope could deliver.
Table of contents
- 1. What is a masonry layout?
- 2. The CSS Masonry draft specification
- 3. grid-template-rows: masonry: syntax and behavior
- 4. A first example: an image gallery as a masonry grid
- 5. Alignment and spanning in masonry grids
- 6. Browser flags: how to enable the preview
- 7. Polyfill comparison: JavaScript vs. native CSS
- 8. CSS Masonry approaches compared
- 9. Interop 2025 and the road to standardization
- 10. Summary
- 11. FAQ
1. What is a masonry layout?
A CSS Masonry Layout describes a grid layout in which items are arranged in columns, but the row height is not fixed. Instead, every new item slots into the column with the least amount of used vertical space, much like stones in a wall (hence the name masonry). The result is a dense grid without gaps between elements of different heights, the effect that made Pinterest famous.
The fundamental problem with classic CSS Grid is that grid layouts rely on a strict row and column raster. When items have different heights, you either end up with gaps between them (because the row is as tall as the tallest item) or items need a grid-row-span, which requires knowing their exact height in advance. Neither is workable for dynamic content. Previous solutions relied on JavaScript (Masonry.js, Isotope, react-masonry-css), multi-column layouts (column-count), or absolute positioning, all with significant drawbacks in performance, accessibility, or document order.
The CSS Masonry Draft solves the problem at the level of the layout algorithm itself: the browser calculates the placement of every item using a masonry algorithm, without JavaScript having to measure element heights and compute positions. That is not only simpler to implement, it is also more performant and more accessible, because document order is preserved.
2. The CSS Masonry draft specification
The CSS Masonry feature is part of the CSS Grid Layout Level 3 specification, developed by the CSS Working Group. Its current status is "Editor's Draft," meaning the specification is not yet stable, but the basic API is defined and browser implementations already exist. The specification defines masonry as an extension of the existing grid model: a grid container can use the masonry algorithm instead of the normal grid algorithm on one of its axes.
There was an important debate within the CSS Working Group: Google proposed defining CSS Masonry as a separate property outside of grid (display: masonry), while Mozilla favored integrating it into grid (grid-template-rows: masonry). After a lengthy discussion, the Working Group settled on the grid integration approach, which also matches Mozilla's implementation. That means CSS Masonry can use the entire grid toolbox: gap, alignment, spanning, and named lines.
3. grid-template-rows: masonry: syntax and behavior
The basic syntax for CSS Masonry is simple: grid-template-rows: masonry combined with a normal grid-template-columns definition. The masonry keyword on the row axis activates the masonry algorithm for that direction. Alternatively, grid-template-columns: masonry can be used to create a horizontal masonry (columns grow to the right, items fill in row direction), which is less common but useful for special layouts.
The behavior of the CSS Masonry algorithm works as follows: the container defines the columns normally (for example grid-template-columns: repeat(3, 1fr)). Items are placed in reading order but are not forced into fixed rows; they always fill the shortest available column. gap works normally and creates spacing between all items both horizontally and vertically. Items can be given grid-column: span 2 to stretch across multiple columns.
/* CSS Masonry Draft: basic syntax */
/* Enable masonry on the row axis */
.masonry-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: masonry; /* activates masonry algorithm */
gap: 1rem;
}
/* Responsive masonry: auto-fill columns with min width */
.masonry-responsive {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-template-rows: masonry;
gap: 1.25rem;
}
/* Horizontal masonry (items fill row-by-row) */
.masonry-horizontal {
display: grid;
grid-template-rows: repeat(3, auto);
grid-template-columns: masonry;
gap: 1rem;
}
/* Feature detection: apply masonry only where supported */
@supports (grid-template-rows: masonry) {
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
grid-template-rows: masonry;
gap: 1rem;
}
}
4. A first example: an image gallery as a masonry grid
The classic practical CSS Masonry example is an image gallery with photos of different aspect ratios. With a normal grid, all images would be scaled to the same height, losing their original aspect ratio or leaving gaps. With CSS Masonry, every image keeps its natural aspect ratio, and the algorithm stacks the images into the shortest column without gaps.
An important detail for image galleries: img { width: 100%; height: auto; display: block; } is required so that images keep their natural height and the CSS Masonry algorithm can work correctly. Images with a fixed height would undermine the masonry algorithm, since all images would then have the same height. The block display also prevents the default gap that appears beneath inline images.
For cards with variable text content, such as blog posts with teasers of different lengths or product cards with variable description text, CSS Masonry is even more useful. Instead of stretching every card to the height of the tallest one, or writing JavaScript to keep the spacing even, the browser arranges the cards automatically without gaps. That is the core promise of the specification draft.
5. Alignment and spanning in masonry grids
Since CSS Masonry is defined as a grid extension, the familiar alignment properties still apply. justify-items and align-items work for items inside a masonry container. justify-self can be used on individual items to position them within their column. This is particularly useful for items that are narrower than their column, such as buttons or small images in a CSS Masonry layout.
Spanning in CSS Masonry is limited to the column axis. grid-column: span 2 lets an item span two columns, which works just like in a normal grid. grid-row: span 2 makes no sense in a masonry layout, since the row axis is controlled by the masonry algorithm and has no fixed rows. That is an important difference from regular grid spanning.
/* CSS Masonry Draft: alignment and spanning */
.masonry-gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
gap: 1rem;
align-tracks: start; /* align items to the top of each track */
}
/* Featured item spans two columns */
.masonry-gallery .featured {
grid-column: span 2;
}
/* Small item: centered within its column */
.masonry-gallery .small-badge {
justify-self: center;
width: 80%;
}
/* Images: natural aspect ratio preserved */
.masonry-gallery img {
width: 100%;
height: auto;
display: block;
border-radius: 0.5rem;
object-fit: cover;
}
/* Masonry with named grid lines for semantic spanning */
.masonry-layout {
display: grid;
grid-template-columns: [main-start] 1fr 1fr [sidebar-start] 1fr [sidebar-end main-end];
grid-template-rows: masonry;
gap: 1.5rem;
}
6. Browser flags: how to enable the preview
The CSS Masonry Draft is available in Firefox and in Chromium-based browsers behind experimental flags. In Firefox, grid-template-rows: masonry can be enabled since Firefox 77 via layout.css.grid-template-masonry-value.enabled in about:config. In Chrome Canary and Chromium Nightly builds, the feature is available via the #enable-experimental-web-platform-features flag in chrome://flags. Production Chrome and Safari still do not support CSS Masonry without a flag as of May 2026.
For development, Firefox Nightly is recommended as the reference browser for CSS Masonry features. The Firefox implementation follows the current specification most closely, since Mozilla played a major role in developing the CSS Masonry proposal. Chrome Canary is useful for cross-browser testing, but the implementations can differ in details while the specification is still unfinished.
For production environments, @supports (grid-template-rows: masonry) is the right strategy: where supported, the native CSS Masonry layout is used, and elsewhere a multi-column or flexible grid fallback applies instead. This progressive enhancement approach lets you experiment with the native API today without confronting unsupported users with broken layouts.
7. Polyfill comparison: JavaScript vs. native CSS
Before the CSS Masonry Draft, JavaScript libraries were the only viable option for true masonry layouts. The best known is Desandro's Masonry.js, one of the most widely used layout libraries since 2010. It measures the height of every element, calculates positions, sets absolute positions, and reacts to resize events. The result is correct, but expensive: the initial layout requires DOM reads for every item (layout thrashing), resize events must be debounced, and JavaScript has to load and execute before the layout is correct.
An alternative CSS-only approach without JavaScript is column-count or columns: elements are arranged in columns, but in column order rather than reading order. An item in column 1 appears before an item in column 2, regardless of which one comes first in the HTML. That is problematic for content with a semantic order, such as blog posts sorted by date, since screen readers and tab navigation follow DOM order, not the visual column arrangement. Native CSS Masonry solves this problem because it preserves document order.
8. CSS Masonry approaches compared
The different masonry implementation approaches differ fundamentally in performance, accessibility, and implementation effort.
| Approach | DOM order | Performance | Browser support |
|---|---|---|---|
| CSS Masonry Draft | Preserved | Native, no JS | Behind flags only |
| Masonry.js | Preserved | JS overhead, layout thrashing | All browsers |
| column-count CSS | Column order | Native, no JS | All browsers |
| Grid + grid-row: span | Preserved | Native | All browsers |
| Flexbox multi-column | Column order (manual) | Native | All browsers |
The "Grid + grid-row: span" variant, the best known CSS-only alternative without CSS Masonry, only works for content with known heights. You divide the content height by a fixed row height (for example 10px) and set grid-row: span X accordingly. That is high maintenance, requires either JavaScript for the calculation or fixed heights, and fails for dynamic content. It is the best possible CSS approximation without native CSS Masonry, but not a full replacement.
/* CSS Masonry alternatives: current best practices */
/* Option 1: column-count (DOM order caveat!) */
.gallery-columns {
columns: 3 240px; /* 3 columns, min 240px each */
column-gap: 1rem;
}
.gallery-columns > * {
break-inside: avoid; /* prevent items from splitting */
margin-bottom: 1rem;
}
/* Option 2: CSS Grid with JS-calculated span (dynamic) */
.masonry-grid-approx {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-auto-rows: 10px; /* small row unit for JS span calculation */
gap: 1rem 1rem;
}
/* JS sets: element.style.gridRowEnd = 'span ' + Math.ceil(height / 10) */
/* Option 3: Progressive enhancement with @supports */
.gallery { columns: 3; column-gap: 1rem; }
.gallery > * { break-inside: avoid; margin-bottom: 1rem; }
@supports (grid-template-rows: masonry) {
.gallery {
columns: unset;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-template-rows: masonry;
gap: 1rem;
}
.gallery > * { margin-bottom: 0; }
}
9. Interop 2025 and the road to standardization
The Interop project is a collaboration between browser vendors Apple, Google, Microsoft, and Mozilla to improve cross-browser compatibility for important web features. CSS Masonry was a candidate for Interop 2025 and was assigned high priority, which signals that browser vendors consider the feature important. Interop features receive coordinated implementation work across all participating browsers, historically the fastest path from a draft to baseline status.
For developers, this means CSS Masonry is not a speculative feature but one with a clear standardization path. The question is not whether but when it will be available without flags in every browser. A conservative estimate based on similar features is 12 to 24 months after Interop adoption. That means teams should start experimenting with the native API today, build fallback strategies, and prepare for the progressive enhancement transition.
Mironsoft
Modern CSS layouts, masonry galleries, and Hyva theme development
Masonry layouts today, without the JavaScript overhead?
We implement masonry galleries with progressive enhancement: native CSS Masonry for supporting browsers, elegant column-count fallbacks for everyone else, while preparing projects for full browser support.
Gallery layouts
Masonry galleries for Magento product pages and blog listings, with CSS and a JS fallback
Progressive enhancement
An @supports-based strategy for native masonry with a robust fallback
Hyva integration
Masonry layouts in Tailwind v4 and Alpine.js components for Hyva themes
10. Summary
The CSS Masonry Draft brings native masonry layout through grid-template-rows: masonry as part of the CSS Grid Level 3 specification. The algorithm places items into the shortest available column, preserves DOM order, and makes JavaScript libraries such as Masonry.js unnecessary. Gap, alignment, and column spanning from the regular grid model all work fully.
As of May 2026, CSS Masonry is available in Firefox Nightly and Chrome Canary behind flags. @supports (grid-template-rows: masonry) enables progressive enhancement: the native API for supporting browsers, a column-count fallback for everyone else. With Interop 2025, the standardization path is clear. Projects that need masonry today should prepare the native API and build with robust fallbacks.
CSS Masonry Draft: the essentials at a glance
Syntax
display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: masonry; gap: 1rem;
Browser support (May 2026)
Firefox Nightly (layout.css.grid-template-masonry-value.enabled) and Chrome Canary (#enable-experimental-web-platform-features). No production support without a flag.
Advantages vs. JS polyfills
No layout thrashing, DOM order preserved, no JavaScript overhead, native grid features (gap, alignment, spanning) available.
Fallback today
@supports strategy: columns: 3 as a fallback, @supports (grid-template-rows: masonry) for native masonry. Progressive enhancement without compromises.