I recently got a report from a client running a high-end photography portfolio. The site looked great, but their Largest Contentful Paint was close to 6 seconds on mobile. The cause was a heavy JS solution they used to get a native Masonry layout look. It blocked rendering, so users sat in front of a white screen while a 25KB script worked out where to put a handful of images.
My first thought was to throw more code at it. Lazy-load the script, or swap in a lighter library. That is the trap we have all been in for a decade. We reach for a library the moment a UI problem looks complicated and forget that the browser has moved on since. If you care about performance optimization, start with what the platform already gives you.
The problem with JS-heavy layouts
Fifteen years ago we had no choice. We had to support IE6, and even rounded corners needed JS or “clever” sprite hacks. Today, most of what we still pull in Lodash or Floating UI for is built into the browser. The 2024 Web Almanac puts the median page weight at 2MB, mostly JavaScript. We are shipping more code to phones than ever, and for what?
A library for a native Masonry layout makes the browser wait. The script has to load, parse and execute before the first image knows where it goes. On a slow 4G connection that is a death sentence for your conversion rate. The best code here is the code you never have to download.
What native masonry layout fixes
For years the tidy way to do masonry without JS was CSS columns. The catch is that columns flow vertically. With 10 items, item 2 lands at the top of the second column instead of next to item 1, which wrecks reading order and accessibility. That is why the new MDN documentation on CSS masonry matters. We finally get to pack items into the tightest gaps without breaking the document’s logical flow.
That is what grid-lanes (the new display type) is for. The engine does the work, so nothing recalculates positions on every window resize. I wrote more about this in my post on modern CSS and why the JS-first habit is on its way out.
/*
* The bbioon_native_masonry helper
* Note: This uses the upcoming grid-lanes spec
*/
.bbioon-gallery-container {
display: grid;
gap: 1.5rem;
/* Defining columns but letting rows pack naturally */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
grid-template-rows: masonry; /* This is the magic line */
}
.bbioon-item-featured {
grid-column: span 2; /* Items can still span tracks! */
}
/* Fallback for older browsers using CSS columns */
@supports not (grid-template-rows: masonry) {
.bbioon-gallery-container {
column-count: 3;
column-gap: 1.5rem;
}
.bbioon-item {
break-inside: avoid;
margin-bottom: 1.5rem;
}
}
Is it ready for production?
I am a pragmatist about this. You cannot flip a switch and expect every browser to support a native Masonry layout tomorrow. But the Chromium and Firefox teams are moving fast on it. As the Smashing Magazine piece I took this from points out, vendors are finally listening to developers who are done with the JS-only route.
@supports lets you ship this today. Modern browsers get the fast path and the stragglers get a working fallback, which costs you about ten lines of CSS. In 14 years the bet that has paid off most consistently for me is the one on native platform features.
This gets complicated fast. If you are tired of debugging someone else’s mess and just want the site to be quick, drop me a line. I have probably seen it before and fixed it.
What it comes down to
- JS libraries for layout are a performance liability in 2025.
- A native Masonry layout with
grid-template-rows: masonrykeeps DOM order and accessibility intact. - Leaning on browser primitives leaves you less code to maintain later.
- A slow site is a reputation problem, not only a metric.