Swift icon
Published at
Updated at
Reading time
5min

The very new CSS masonry Layout functionality coming with CSS grid will ship in browsers eventually.

This post shares what you need to do to get started and implement masonry layout in your sites, and it explains feature detection in CSS and JavaScript. It's not going into the nighty-gritty details of masonry grid layouts. If you want to dive into the topic, find additional resources at the end of the article.

That's my site's implementation for browsers that do or don't support the new masonry grid layout.

Comparison of the today i learned section on stefanjudis.com with and without masonry support

On the left, you see a standard CSS grid layout. Unfortunately, the content in the grid has one problem. The included sections and areas substantially vary in height. Some elements hold only a few entries whereas others include more than thirty entries. Having these sections next to each other in a grid leads to a lot of empty whitespace. That's why I manually adjusted particular cells to span over multiple columns.

For example, the area for CSS spans over three rows using grid-row: auto/span 3. Similar to most manual adjustments, this is far away from being perfect.

.area-css {
  grid-row: auto/span 3;
}

In these situations the masonry grid layout comes into play and shines. It enables you to make the best out of all the available space without manual adjustments. 🎉

One the right, the elements for each area are automatically readjusting depending on their height. The grid is laid out automatically. It's beautiful!

The masonry grid is based on CSS similar to the snippet you find in the MDN documentation for CSS grid with Masonry.

.container {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  grid-template-rows: masonry;
}

The code above leads to a grid similar to my site and the one below.

Masonry grid example

CSS masonry is not cross-browser supported yet

First things, first. At the time of writing, there's no cross-browser support for masonry grid layout. When you're looking at caniuse.com for the masonry layout, you'll find out that there's no browser at all. No browser is shipping masonry layouts, and it's only Firefox rushing ahead with an implementation behind a flag.

caniuse.com support table for Masonry layout showing no support except Firefox with a behind-a-flag implementation

To get started, open Firefox and open about:config (you can type it into the URL bar) and enable the boolean flag for layout.css.grid-template-masonry-value.enabled.

about:config screen with enabled masonry config option

Once you enabled masonry grid layout, head over to my TIL overview. A celebration message, confetti and the masonry grid layout spanning the whole page will greet you.

Screenshot of the site: "Looks like your browser supports masonry grid layout... Cool beans!"

Feature detection of new CSS features such as masonry grid layout

There's one critical fact about web platform feature adoption. You can't just throw new and only partially supported features into your CSS and call it a day. You always have to consider a fallback behaviour.

Is the new feature degrading gracefully? Does everything still work when the browser doesn't support it? Is the new web platform feature mission-critical or is just fine, if it doesn't work?

These questions are essential to guarantee a good user experience, and that's why my site includes feature detection in CSS and JavaScript to define a fallback behaviour.

Feature detection in CSS

To check if a browser supports a new CSS feature, leverage the @supports feature query. Use the feature query with the CSS declaration you want to test and apply your CSS if a browser does or does not support the new CSS feature.

I added a new class (list-masonry) to my code base that should apply the masonry layout if the browser supports it.

/* define list-masonry if the browser support Masonry */
@supports (grid-template-rows: masonry) {
  .list-masonry {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-gap: var(--grid-gap);
    grid-template-columns: repeat(auto-fill, minmax(16em, 1fr));
    grid-template-rows: masonry;
  }
}

Additionally, to hide and show the celebration message, I added a new utility class. The class works similar to classes such as hide-on-small that hide elements depending on viewport sizes.

The difference to viewport dependent classes is that show-if-supports-masonry doesn't rely on a media query but a feature query.

show-if-supports-masonry initially sets the element's display property to none. If a browser supports masonry layout, the feature query overwrites the "hiding CSS" with display: block.

/* hide element initially */
.show-if-supports-masonry {
  display: none;
}

/* show elements if the browser support masonry layout */
@supports (grid-template-rows: masonry) {
  .show-if-supports-masonry {
    display: block;
  }
}

Paired with the following HTML, I can show a celebration message depending on the browser feature support.

<div class="show-if-supports-masonry">
   🎉 Looks like your browser supports masonry grid layout... Cool beans! 🎉
</div>

Features detection in JavaScript

So far, I applied the masonry grid layout and showed a nifty message when it was supported. But I wanted to celebrate the early adopters even more!

The people who are browsing my site and maybe even subscribed to my newsletter might know that I have confetti canons in several areas on my site.

Little quick trick: You can add confetti to your site without any tooling by leveraging skypack. Skypack is a CDN for JavaScript packages that expose ES modules. To add a confetti canon to your site, all you have to do is:

  • add a <script type="module"> to your site to able to use import statements
  • load the confetti-canvas module from Skypack using import confetti from 'https://cdn.skypack.dev/canvas-confetti' or import('https://cdn.skypack.dev/canvas-confetti')
  • throw confetti by calling confetti()

Skypack and ES modules are fantastic and I find myself adding these tiny code blocks more and more these days.

<script type="module">
  // load and display confetti
  // if masonry grid layout is supported
  if (CSS.supports("grid-template-rows", "masonry")) {
    import('https://cdn.skypack.dev/canvas-confetti')
      .then(({default: confetti}) => confetti())
  }
</script>

The interesting part of this confetti snippet is the CSS feature detection using CSS.supports. It allows you to handle not supported CSS features in JavaScript. If a CSS feature is necessary to your site, you could load polyfills or offer an alternative experience.

I love the web and its features these days!

Summary

That was it to implemented CSS grid Masonry on my site. The not-supporting browsers are showing the grid with cells spanning over several columns. That's good enough for my site!

On the other hand, the site includes confetti and a grid that's not wasting and screen space for supporting browsers.

And all this functionality is feature detected using @supports in CSS or CSS.supports in JavaScript. 🎉

Additional resources

Related Topics

Related Articles