How to add a real masonry layout in Easy Posts element

You probably have noticed that the items in the Masonry templates, for the Easy Posts, are ordered from top to bottom, instead of the classic left to right.

What we have
What we want

That's totally normal as they are made with Flexbox. I won't explain why but you can find some very useful information here:

https://stackoverflow.com/questions/44377343/css-only-masonry-layout

In this tutorial, we are going to use the famous Masonry library.
By chance this library is already included in Wordpress, so we don't have to load the file. But we still have to enqueue it.

Step 1

Enqueue the file :

wp_enqueue_script('masonry');

[ see HOWTO to learn how to enqueue files ]

Step 2

Add the Easy Posts element and choose the template Masonry - Image w/Title Overlay

We can use any template but we will start with this one as an example.

Step 3

Select your Easy Posts element and go to Template CSS.

At the top we have:

%%EPID%% .oxy-posts {
  display: block;
  column-count: 3;
  column-gap: 2em;
  margin-bottom: 4em;
}

%%EPID%% .oxy-post {
  margin-bottom: 2em;
  break-inside: avoid;
  position: relative;
  overflow: hidden;
  display: flex;
  background-color: #000;
}

Replace by:

%%EPID%% .oxy-posts {
  margin:0 auto;
}
%%EPID%% .oxy-post {
  width:calc(33.3333% - 13.3333px);
  margin-bottom: 20px;
  break-inside: avoid;
  overflow: hidden;
  background-color: #000;
}

We don't use the flexbox and the columns, so we replace them with a good old 'width'.

Then we add:

@media (max-width: 1120px) {
  %%EPID%% .oxy-post {
    width:calc(50% - 10px);
  }
  
}

@media (max-width: 768px) {
  %%EPID%% .oxy-post {
    width:100%;
  }
}

At the bottom, we can remove:

@media (max-width: 1120px) {
  %%EPID%% .oxy-posts {
    column-count: 2;
  }
  
}

@media (max-width: 768px) {
  %%EPID%% .oxy-posts {
    column-count: 1;
  }
}

There are no mistakes here, we have added some .oxy-post and removed some .oxy-posts

Now you are probably wondering why we use these calc and why these numbers.
Basically, we want the gallery ( 3 columns with a gap of 20px) to fill the container, so we have to calculate the width of each item.

The solution is very obvious and can be easily explained like this :

  • $number_of_cols = 3;
  • $column_width = 100 / $number_of_cols;
  • $item_width_diff = $gutter * ($number_of_cols - 1) / $number_of_cols;

.oxy-post { width: calc($column_width - $item_width_diff); }

Well, that was actually not obvious at all, and I am really happy to have found the solution here:
https://stackoverflow.com/questions/30935502/masonry-column-width-percent-gutter

Step 4

Add a Code Block and paste this code

(function($) {

    // init Masonry
    $('.oxy-posts').masonry({
        // options
        itemSelector: '.oxy-post',
        gutter: 20,
        percentPosition: true,
        horizontalOrder: true
    });

}(jQuery));

We are not totally done yet but you can check if it's working (in the frontend).

Once again, I won't give all the details as everything is well explained in the official page: https://masonry.desandro.com/options.html

Step 5

As we are dealing with images, it's better to use the imagesLoaded library.
The good news is that it's also included in Wordpress and it was already loaded when we added masonry.

As explained here: https://masonry.desandro.com/layout.html#imagesloaded

Unloaded images can throw off Masonry layouts and cause item elements to overlap. imagesLoaded resolves this issue.

So our final javascript will be :

(function($) {

    // init Masonry
    var $grid = $('.oxy-posts').masonry({
        // options
        itemSelector: '.oxy-post',
        gutter: 20,
        percentPosition: true,
        horizontalOrder: true
    });

    // layout Masonry after each image loads
    $grid.imagesLoaded().progress(function() {
        $grid.masonry('layout');
    });

}(jQuery));

Note

The version of Masonry included in Wordpress 5.1 is an old version (v3.3.2). It should be enough in most case, but if you need to use some more recent features, you can download and enqueue the last version : https://github.com/desandro/masonry/releases