In the Lab: A Custom Post Grid block using WP_Query

Custom Post Grid Block for WordPress Gutenberg How To Tutorial

Welcome back to the Lab.

We’ve seen a bunch of people build some great custom blocks using WP_Query, and a bunch more ask how it can be done. So in this tutorial we’re going to show you. 🙂

WP_Query is a WordPress class that provides numerous functions for common tasks within The Loop. A simple use case is wanting to display related posts on a single post page. In a page template, or in our case in a block, you can use WP_Query to loop through posts according to set properties such as the shared category with the single post.

If that’s still not 100% clear for you, check out the offical docs. Also, this tutorial should help show you how it all fits together.

So the custom block we’re building to today is going to be a simple Posts Grid block that lets you:

  • Select the post-type to display
  • Set the number of posts to display

When done, it’s going to look like this.

Custom Post Grid Block for WordPress Gutenberg How To Tutorial
Our Custom Post Grid Block

Let’s do this!

So our local setup for building the block looks like:

  • Theme: Atomic Blocks Child Theme
  • Plugins: Block Lab

In previous tutorials, our block fields have corresponded with individual content pieces, images, or style customisations in the block. For this block, we’re actually going to use the block fields to set the properties for our query. Now there are dozens or properties that can be passed to WP_Query. It’s worth looking over the documentation to see what is possible.

As mentioned further up, our block fields are:

Field LabelField SlugField TypeField Location
Number of Postsnumber-of-postsRangeEditor
Post Typepost-typeSelectEditor

So in our WordPress Admin and with the Block Lab plugin active, we go to Block Lab > New Block.

Give our new block the title of Post Grid and configure the block properties. This is what we have:

Custom Post Grid Block - Block Properties
Custom Block Properties

Now let’s add all our fields as per our table above:

Custom Post Grid Block - Fields

For the Select field, we set our choices as:

Custom Post Grid Block - Select Field Choices

Hit Publish.

You’ll notice that when you hit publish that at the top of the page a prompt appears telling us that our next step is to create a PHP template file and gives us the file name and path for this.

Custom Post Grid Block - Template Prompt
Custom Block Template Prompt

So let’s open up our text editor and create the file. In our child theme, in the top level folder, we’re going to add a new folder called blocks. In this folder we’re going to create a file called (as per the prompt above) block-post-grid.php.

We’re also going to create a CSS file where we are going to add our CSS code for styling the block. This file will be named exactly the same as the main PHP file except the file extension will be .css instead of .php. The Block Lab plugin auto-magically pairs these two files together. So for our block it will be block-post-grid.css.

With these files saved, we can go back to our Block Editor in WordPress, hit refresh, and we’ll see that our new template file is being picked up now as the prompt has disappeared and now instead shows the template file path.

Custom Post Grid Block - Title

Great! Our template file is added. Now let’s build it out.

In our PHP template file lets set up our WP_Query Loop. Our code will look like this:

<div class="block-post-grid <?php block_field( 'className') ?>">
    
    <?php
    // Variables
    $post_count = block_value( 'number-of-posts' );
    $post_type  = block_value( 'post-type' );

    // WP_Query arguments
    $args = array(
        'post_type'         => array( $post_type ),
        'posts_per_page'    => $post_count,
    );

    // The Query
    $post_grid_query = new WP_Query( $args );

    // The Loop
    while ( $post_grid_query->have_posts() ) {
        $post_grid_query->the_post();
        
    }

    // Restore original Post Data
    wp_reset_postdata();
    ?>

</div>

The things to note here are:

  • We’ve wrapped everything in a <div> and given it a CSS class of block-post-grid as well as using the reserved className to add the Additional Class
  • We’ve set up a few variables by using the Block Lab block_value function and interacting with our 2 block fields
  • We’ve defined the arguments (properties) that we want to pass to WP_Query using these variables
  • We’ve started the Query
  • We’ve started the Loop
  • We’ve reset the postdata

It’s important that we reset the post data as this custom block can be dropped in on any page or post and that the rest of the post/page content will need to continue being “looped” through after this block.

Now let’s fill out the content of our Loop. This is what will be rendered each time the Loop runs.

Our Loop code looks like this:

<div class="block-post-grid--post">
    <div class="block-post-grid--post-thumbnail" style="background-image: url('<?php the_post_thumbnail_url( 'large' ); ?>');">
    </div>
    <div class="block-post-grid--post-content">
        <h4><?php the_title(); ?></h4>
        <p><?php the_excerpt(); ?></p>
        <a href="<?php the_permalink(); ?>" >Read More</a>
    </div>
</div>

Note that:

  • We’re got a few new CSS classes now that handle styling for each individual post
  • We’ve got the post thumbnail (feature image) at the top, which we’ve set as a background image on a div
  • As we’re in the Loop now, we can access the post title, excerpt, and post link (permalink) nice and easily

So with all our code together, our PHP template file looks like this:

<div class="block-post-grid <?php block_field( 'className') ?>">
    
    <?php
    // Variables
    $post_count = block_value( 'number-of-posts' );
    $post_type  = block_value( 'post-type' );

    // WP_Query arguments
    $args = array(
        'post_type'      => array( $post_type ),
        'posts_per_page' => $post_count,
    );

    // The Query
    $post_grid_query = new WP_Query( $args );

    // The Loop
    while ( $post_grid_query->have_posts() ) {
        $post_grid_query->the_post();
        ?>

        <div class="block-post-grid--post">
            <div class="block-post-grid--post-thumbnail" style="background-image: url('<?php the_post_thumbnail_url( 'large' ); ?>');">
            </div>
            <div class="block-post-grid--post-content">
                <h4><?php the_title(); ?></h4>
                <p><?php the_excerpt(); ?></p>
                <a href="<?php the_permalink(); ?>">Read More</a>
            </div>
        </div>

        <?php
    }

    // Restore original Post Data
    wp_reset_postdata();
    ?>

</div>

So that’s it for our HTML and PHP. This is now a functional block, but now we need to make it look nice. Over in our CSS template file (block-post-grid.css), let’s add the following CSS.

.block-post-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-gap: 80px;
}

.block-post-grid--post {
    border-bottom: 1px solid #f4f4f4;
    padding-bottom: 40px;
    margin-bottom: 40px;
}

.block-post-grid--post-thumbnail {
    height: 240px;
    background-size: cover;
    background-position: center;
}

.block-post-grid--post-content {
    padding: 30px 40px 0 40px;
    margin: -40px 40px 0 40px;
    background-color: #fff;
}

.block-post-grid--post-content h4 {
    text-decoration: none;
    font-family: sans-serif;
    color: #2C2936;
}

.block-post-grid--post-content p {
    font-family: sans-serif;
    font-size: 16px;
    margin-left: 20px;
    color: #67607D;
}

.block-post-grid--post-content a {
    position: relative;
    text-decoration: none;
    font-family: sans-serif;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #5C34E8;
    margin-left: 20px;
}

.block-post-grid--post-content a:after {
    display: block;
    position: absolute;
    content: "";
    border-top: 3px solid #5C34E8;
    border-right: 3px solid #5C34E8;
    border-top-right-radius: 3px;
    width: 8px;
    height: 8px;
    transform: rotate( 45deg );
    top: 4px;
    right: -20px;
    transition-duration: 0.1s;
}

.block-post-grid--post-content a:hover:after {
    right: -26px;
}

@media (max-width: 720px) {
    .block-post-grid {
        grid-template-columns: 1fr;
    }
}

So what’s going on here?

  • We’re using CSS Grid to handle our columns.
  • We’ve set a fixed height for our Thumbnail div. This means that no matter the actual size of the post thumbnail (feature image), it will display at the same height.
  • We’ve used some padding and a bit of negative margin on our post content to get our overlapped effect with the thumbnail image.
  • Some styling on paragraph and anchors
  • We’ve used the pseudo class :after on our anchor to give us our little arrow
  • We’ve used the pseudo class :hover on our anchor to give us the hover effect on the arrow
  • We’ve used a media query to set our grid to one column on smaller screens

And that is the final piece of this Post Grid puzzle. Let’s go create a new Page in WordPress, add our block, fill out the fields and see what it looks like.

In the editor, we can select and add the block to the page:

Custom Post Grid Block - Adding the Block
Adding our custom block to the page

Fill in the fields:

Custom Post Grid Block - Filling out the Fields
The fields in the Editor

And check it out:

Custom Post Grid Block - Finished block on the Frontend

Looking good!!!

So this block is a nice and easy example of how to use WP_Query. With all the power that WP_Query brings to the table, there are some pretty cool things you could build with it. If you build something yourself, share a link in the comments below. We’d love to check it out!

If you want to learn more, have a look at these previous tutorials:

Happy block building!

Leave a Reply

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