Lazy loading images in a masonry grid

With lazy loading, you only load images when they are in the visible area of the visitor. Combining this method with a masonry grid can cause problems because the images are not loaded yet when the position of the grid items is calculated. Here I show you how to solve that.

The problem with lazy loading and masonry grids

A masonry grid script positions the grid items absolute after calculating the position for the items based on its width and height. But if the images are loaded after running the script because of lazy loading, the script returns wrong positions. The result can look something like that:

A masonry grid with overlapping items because the images are lazy loaded.

Not what we want and expect, and we do not want to wait until all images are loaded to run the script. So what can we do?

The solution: width and height as inline styles

The grid item’s markup looks like that:

<article class="col-4"> <figure> <img class="lazyload" data-src="[…]" data-srcset="[…]" data-sizes="[…]"> <noscript><img src="[…]"></noscript> </figure> <div> <h2>Zigarettenwerbung</h2> <ul> <li class="category">[…]</li> <li class="date">[…]</li> <li class="team">[…]</li> </ul> </div> </article>
Code language: JavaScript (javascript)

The solution for our problem is to add the width and height of the image to the figure element. So the masonry script will consider the space of the not-yet-loaded images correctly while calculating the positions. How you get the width and height depends on how you generate the grid. I used WordPress and the plugin Advanced Custom Fields to create the grid from the screenshot, and get the width and height from the image object.

To avoid issues with this solution and responsive design, you should destroy the masonry grid if the grid’s wrapper is not wide enough for the widest grid image. Otherwise, the calculated position is not going to be correct (but I am sure there is a solution for that too 🙂 ).

You can see the grid implementation live on

Leave a Reply

Your email address will not be published. Required fields are marked *