Create a true masonry layout

By: on Jun 6, 2024

In a masonry style layout, elements of different heights are displayed in a staggered way. We typically see these layouts on websites like Pinterest. This has become a very popular pattern in UI design, because it allows the display of elements in different dimensions with a grid format.

There are three technical requirements for it to be a true masonry layout:

  1. The items are different heights.
  2. The items are ordered in rows and not in columns, typically left to right.
  3. There is a set number of columns, and the columns are contained.

Currently to create a true masonry layout you still need to use a JavaScript approach, like David DeSandro's influential Masonry JavaScript library, which has been available since 2010. Optionally you may also need the imagesLoaded JS library that works as a callback when you need to wait for the images to be loaded before running the Masonry JS.

The callback is a good practice, because the masonry items are going to be dynamically positioned absolute. So there could be cases where if the images are not loaded before the Masonry JS runs, things could get positioned wrong.

Masonry JS Library

The Masonry library is used to create a dynamic grid layout. It automatically positions elements in the most optimal way, filling in gaps and creating a "masonry" effect where the elements are aligned in a visually appealing manner.

imagesLoaded JS Library

The imagesLoaded JavaScript library detects when images have been loaded in the browser. It is often used in conjunction with Masonry to ensure that all images are fully loaded before the layout is applied.

Here's an example of using the Masonry and imagesLoaded JavaScript libraries together to create a true masonry layout.

Example of true masonry

Masonry Brick #1
Masonry Brick #2
Masonry Brick #3
Masonry Brick #4
Masonry Brick #5
Masonry Brick #6
Masonry Brick #7
Masonry Brick #8
Masonry Brick #9

Masonry JS key features

  • Dynamic Positioning: It dynamically positions elements to create a visually appealing layout without fixed rows or columns.
  • Column Widths: Allows items to have varying heights and widths, accommodating different content sizes.
  • Responsive: Adapts to different screen sizes by rearranging the items based on the container's width.
  • Horizontal order: By setting horizontalOrder: true in the Masonry options, we ensure that the items are laid out in the left to right order horizontally, preventing the issue where the order is not quite correct.

imagesLoaded JS key Features

  • Prevent Overlapping: If Masonry tries to layout items before all images are fully loaded, it can result in incorrect positioning and overlapping of items. imagesLoaded ensures that the Masonry layout is applied only after all images are fully loaded, preventing these issues.
  • Smooth Loading: Ensures a smoother and more visually appealing loading experience for users by correctly positioning elements once all images are ready.

Example Code

Here’s how these libraries are used together in a typical setup:

<style>
* { box-sizing: border-box; }
/* force scrollbar */
html { overflow-y: scroll; }
.masonry-item {
width: 33.333%;
padding: 1%
}
.masonry-item img {
display: block;
max-width: 100%;
}
.masonry {
counter-reset: masonry-item;
}

.masonry-item:before {
counter-increment: masonry-item;
content: counter(masonry-item);
display: block;
color: white;
padding-top: 0.2em;
text-align: center;
font-size: 1.4rem;
}
/* clearfix */
.masonry:after {
content: '';
display: block;
clear: both;
}
</style>
<h3>Example of true masonry</h3>
<div class="example-bg">
<div class="masonry">
<div class="masonry-item"><img src="https://unsplash.it/700/800?image=1" alt="Masonry Brick #1" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/600?image=2" alt="Masonry Brick #2" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/400?image=3" alt="Masonry Brick #3" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/500?image=4" alt="Masonry Brick #4" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/700?image=5" alt="Masonry Brick #5" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/300?image=6" alt="Masonry Brick #6" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/500?image=7" alt="Masonry Brick #7" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/650?image=8" alt="Masonry Brick #8" class="masonry-content"></div>
<div class="masonry-item"><img src="https://unsplash.it/700/350?image=9" alt="Masonry Brick #9" class="masonry-content"></div>
</div>
</div>
<!-- Load Masonry and imagesLoaded libraries -->
<script src="https://unpkg.com/masonry-layout@4.2.2/dist/masonry.pkgd.js"></script>
<script src="https://unpkg.com/imagesloaded@4/imagesloaded.pkgd.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var elem = document.querySelector('.masonry');
var msnry = new Masonry(elem, {
// options
itemSelector: '.masonry-item',
columnWidth: '.masonry-item',
percentPosition: true,
horizontalOrder: true
});
imagesLoaded(elem, function () {
msnry.layout();
});
});
</script>

Here is a breakdown of the above code:

  1. Document ready event lister to ensure teh script does not run until after the DOM has loaded.
  2. Select the masonry container by selecting the element with the .masonry class.
  3. Initialize the masonry instance on the selected element with the specified options.

Conclusion

It may be questionable to use JavaScript libraries to do layout, but until, or if, CSS has a fully supported browser option, this is what we have to work with. If you don't need the items to be ordered left to right in rows, there is a simple CSS multi-column layout module. There is also a light weight version of the Masonry JS called Colcade that also may be a good option.

Resources