GenerateBlocks query loop and grid masonry layout
GeneratePress Premium plugin adds functionality for masonry layout archives through the Customizer (Layout->Blog).
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:
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.
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.