2022-05-18 // 408 words // 2 minute read

Masonry without JavaScript

Masonry is a common web design tool, and has existed in some form or another for over a decade. The most common method to achieve the effect is with JavaScript libraries such as this one by David DeSandro. These libraries are effective, but may not always be the best option. In environments where JavaScript may not function properly, as is common with TOR users, masonry layouts may appear incorrect or even fail to load entirely.

Flexbox may serve as a JavaScript free alternative. As of the writing of this article, caniuse.com reports that 98% of all users’ browsers will render flex layouts properly. An additional advantage to flex is the ease of implementation. We can begin by creating a div to hold our images:

<div class="masonry">
    <img src="https://placekitten.com/600/400">
    <img src="https://placekitten.com/500/700">
    <img src="https://placekitten.com/600/600">
    <img src="https://placekitten.com/200/300">
    <img src="https://placekitten.com/900/700">
    <img src="https://placekitten.com/600/400">
    <img src="https://placekitten.com/500/700">
    <img src="https://placekitten.com/600/600">
    <img src="https://placekitten.com/200/300">
    <img src="https://placekitten.com/900/700">
</div>

Now, we can set the div containing the elements to display with flex:

.masonry {
    display: flex;
}

This puts all our images onto one line, so we need to adjust some additional parameters to make it look like masonry. First, we can tell CSS to allow our images to wrap.

.masonry {
    display: flex;
    flex-wrap: wrap;
}

I want my layout to be aligned to the top-left:

.masonry {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: flex-start;
  align-content: flex-start;
}

The images are close to each other, so let’s add a gap:

.masonry {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  align-content: flex-start;
  gap: 10px;
}

Right now we’re starting to see something that looks like masonry, but every image is a different size. To fix this, we can set a uniform height and allow the width to be determined automatically:

.masonry img {
    height: 35vh;
}

And that’s it! We now have a rudimentary masonry grid using nothing but 12 lines of CSS:

.masonry {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: flex-start;
  align-content: flex-start;
  gap: 10px;
}

.masonry img {
  height: 35vh;
}

To learn more about flexbox, check out this article from MDN. For a quick reference, I like this website by Malven Co.