GenerateBlocks query loop and grid masonry layout

GeneratePress Premium plugin adds functionality for masonry layout archives through the Customizer (Layout->Blog).

Masonry layout columns in GeneratePress archives
Masonry layout columns in GeneratePress archives.

There is no such functionality for GenerateBlocks, though, at least at the time of writing this article. I will use a widely known JavaScript library called Masonry but I will also provide a CSS solution at the end!

We will need to create a child theme in order to make our lives easier and keep maintainability. Follow the steps below with me!

JavaScript method

1. Create a query loop

Insert a GenerateBlocks query loop on a page and style is accordingly. For the grid, set a value for the horizontal and vertical gap. The horizontal gap will be responsible for the spacing of out grid items. The vertical gap will not actually work in our case, it will function as a guide for the time being. We will use CSS to create the vertical spacing. You can also set responsive settings for the grid. In my case, I set the Post Template to have a 33.33% width on desktop, 50% width on tablet and 100% width on mobile.

Assign the class of masonry-grid-container for the grid container and the class of has-grid-class for the Post Template container.

Go to your functions.php inside your child theme and enter the following PHP code:

add_filter( 'generateblocks_attr_grid-item', function( $attributes, $settings ) {
	
    if ( isset( $settings['className'] ) && 'has-grid-class' === $settings['className'] ) {
        $attributes['class'] .= ' grid-item';
    }

    return $attributes;
}, 10, 2 );

This will add a class of grid-item to each of the grid columns since it’s not currently possible to do that from the block editor!

We will end up with something like this:

Query loop grid
Query loop grid.

2. Import the masonry library

Go to https://masonry.desandro.com/ and click the button at the top right to download the minified JavaScript file named masonry.pkgd.min.js. Create a js folder inside your child theme and copy the file you have just downloaded in there. Also, create another JavaScript file inside your JS directory, name it masonry-grid-init.js and leave it blank for the time being. Now enter the following PHP code inside your child theme functions.php:

function gm_enqueue_external_library_scripts() {
	wp_enqueue_script( 'masonry-grid', get_stylesheet_directory_uri() . '/js/masonry.pkgd.min.js', array(), false, true );
	wp_enqueue_script( 'masonry-grid-init', get_stylesheet_directory_uri() . '/js/masonry-grid-init.js', array(), false, true );
}
add_action( 'wp_enqueue_scripts', 'gm_enqueue_external_library_scripts' );

This will import the minified script file we have just downloaded along with the initialization file at the footer of our page. Finally enter the following JavaScript initialization code inside the masonry-grid-init.js file.

var grid = document.querySelector('.masonry-grid-container');
var msnry = new Masonry( grid, {
  // options...
  itemSelector: '.grid-item',
  horizontalOrder: true,
  percentPosition: true
});

In this initialization script, we are settings a variable called grid and assign it to the grid container with the class of masonry-grid-container. Then, we create a Masonry() constructor and enter our arguments as options. The itemSelector option sets the class we have assigned for each grid container. The horizontalOrder option lays out items to (mostly) maintain horizontal left-to-right order. The percentPosition option sets item positions in percent values, rather than pixel values. percentPosition: true works well with percent-width items, as items will not transition their position on resize.

Let’s see what we have so far.

Query loop grid with masonry layout applied
Query loop grid with masonry layout applied.

Looking good! Try resizing the browser window and see how the grid items are being rearranged on the fly. You can also have a look at all the other masonry options available for this library.

3. What about a static grid?

In order to apply the masonry layout functionality for a static GenerateBlocks grid, set a class of masonry-grid-container for the grid container as before. Then, set a class of has-grid-class for ALL individual grid item containers.

CSS method

1. Grid setup

David, from GeneratePress, has provided another cool CSS method, as well! Working on our query loop, remove all CSS classes that we have assigned to our grid and post template container. Just to remind you the classes are masonry-grid-container and has-grid-class respectively. Also, remove the grid horizontal and vertical gaps if there are any. Finally, assign the class of has-masonry to the grid container.

2. CSS

Enter the following CSS code in your style.css file of your child theme:

#page .has-masonry {
	display: block;
	font-size: 20px;
}

#page .has-masonry > .gb-grid-column {
	width: unset;
	margin-bottom: 20px;
	display: inline-block;
}

@media (min-width: 1024px) {
	#page .has-masonry {
        column-count: 3;
    }
}

@media (min-width: 769px) and (max-width: 1023px) {
	#page .has-masonry {
        column-count: 2;
    }
}

@media (max-width: 768px) {
	#page .has-masonry {
        column-count: 1;
    }
}

Note the #page selector being added. It’s needed for the layout to be applied on the front end. Also, note the font-size: 20px; in the first selector. It acts as the horizontal spacing for the grid items. I’ve set it to 20px to match the margin-bottom: 20px; which is responsible for the vertical column spacing. I have also created 3 media queries to change the number of columns for desktop, tablet and mobile but your layout may vary.

For the static grid example, just remove the horizontal and vertical grid gaps, if there are any, and replace the grid container class masonry-grid-container with the class of has-masonry. Finally, remove the has-grid-class from all the individual containers.

The only downside of this method is that the grid items will transition their position on resize.