How to build a custom block with ACF (Advanced Custom Fields) and Block Lab

A match made in Australia.

We don’t have a big population down under, but I’m pretty proud of the Open Source work that comes out of this patch of dirt where Christmas is in summer and our Prime Ministers hold beer drinking records. Along with it being the home of Block Lab, Australia is host to one of WordPress’ all-time favourite plugins, Advanced Custom Fields.

So in this tutorial, we’re going big! I’m going to talk and walk you through how to to combine the mighty-morphin powers of Block Lab and Advanced Custom Fields (ACF). We’re going to give IMDB and Rotten Tomatoes a run for their money and build a custom block that displays a whole bunch of your very own personal movie review tiles.

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

The final block in all its hover effect glory

To do all this we’re going to work with:

  1. Block Lab
  2. Advanced Custom Fields
  3. A Custom Post Type (Review)
  4. WP_Query

What we cover here will equip you to thoroughly embrace the new Block Editor (Gutenberg) and build some awesome things in WordPress.

Also, the theme we’re using in the background here is the new twentytwenty theme. It’s pretty nice and optimized well for the Block Editor.

Let’s do it!

Step 1 – Custom Post Type

If you’re unfamiliar with what a Post Type is, let me quickly explain. WordPress has two Post Types out of the box. Posts and Pages. A Custom Post Type (CPT) is just another one that is added to a WordPress site via a theme or plugin. In our case, the Custom Post Type is going to be Reviews.

You have a few options for creating the CPT:

  1. Write the code from scratch and add to your plugin or theme
  2. Use a code generator and then add the code to your plugin or theme
  3. Use a plugin that gives you a UI for registering and configuring them right in the WordPress admin

Depending on your level of skill, start with #3 and then work backwards as you become more experienced over time.

With our selected tool/path of choice, we will create our Reviews CPT. Many of the options can be configured as you prefer, but a few that we need for things to work properly include:

Post Type Keyreview
Name (Singular)Review
Name (Plural)Reviews
Show in REST APItrue

Note that you need to make sure the CPT is available to the REST API. This is so we can interact with it in the Block Editor (Gutenberg) which relies heavily on the REST API.

With the CPT done, we can now create Reviews in our WordPress site. 😀

Review Custom Post Type
Reviews Custom Post Type in Action in the WordPress Admin

Step 2 – Custom Fields

To make our Reviews really powerful, we’re going to create some custom meta fields that will let us add certain pieces of data/content to each review in a consistent way across all reviews. This is where ACF comes in to play. ACF gives us an amazing interface in the WordPress admin for creating and configuring custom meta fields.

With ACF installed and activated, we first create a Field Group. In the WordPress Admin, go to Custom Fields > Add New. Give it a name (ours is Review Fields).

We can then add our fields:

Our custom fields are added using Advanced Custom Fields

We also set this field group to be available only for our CPT Reviews.

And here are the fields in action over when we create a new Review:

The custom fields we created can be seen and used when we add a new Review

With our CPT and custom fields done, now is a good time to create a bunch of reviews. This content will mean that when we build out our custom block using WP_Query, we actually have some content to loop through.

On to the block!

Step 3 – Building the Block

With Block Lab installed and active, in the WordPress admin go to Block Lab > Add New. Give the new block a title (Movie Reviews), an icon, and a category.

Block Fields

We’re not adding many fields to this block. The magic really happens with our CPT, Custom Fields, and WP_Query.

The single block field we add is just so we can select how many review tiles we’d like to display.

We could do a lot of cool stuff with further block fields. We’ll leave them out of this tutorial for now, but there are a few ideas towards the end of the post if you would like to take things even further.

In our Block Builder, the field looks like this:

The field we add to our custom block

Hit Publish!

Block Templates

The block is registered and configured. Now on to templating. If this is your first time with templating, make sure you check out the docs.

Opening up our text editor of choice, in our theme (or child theme) we add the folder blocks. In here we add another folder for our block we’ve just created: movie-reviews. Here we add two files: block.php and block.css. Block Lab gives you a number of options for how you structure your template files. For alternatives, check out these docs.

For our movie-reviews/block.php file, our code looks like this:

<?php

// Variables.
$post_type  = 'review';
$post_count = block_value( 'number' );

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

// The Query.
$review_query = new WP_Query( $args );
?>
<div class="reviews alignwide">
    
    <?php

    // The Loop.
    while ( $review_query->have_posts() ) {
        $review_query->the_post();
        ?>
        <div class="review" style="background-image: url('<?php the_post_thumbnail_url( 'large' ); ?>');">
            <div class="review__content">
                <span class="review__title"><?php the_title(); ?></span>
                <span class="review__director"><?php the_field( 'director' ); ?></span>
                <div class="review__score">
                    <?php
                        $star_count       = get_field( 'score' );
                        $star_count_empty = 5 - get_field( 'score' );

                        // Loop through filled stars.
                        for ( $i = 1; $i <= $star_count; $i++ ) {
                            echo '<span>★</span>';
                        } 

                        // Loop through empty stars.
                        for ( $i = 1; $i <= $star_count_empty; $i++ ) {
                            echo '<span>☆</span>';
                        } 
                    ?>
                </div>
                <span class="review__year">Released: <?php the_field( 'year' ); ?></span>
                <span class="review__one-liner"><?php the_field( 'one_liner_review' ); ?></span>
                <a class="review__imdb-link" target="_blank" href="<?php the_field( 'imdb_link' ); ?>">Visit IMDB</a>
            </div>            
        </div>

        <?php
    }

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

</div>




Let’s take a look at this. The big thing happening here is that we are using WP_Query to loop through our CPT (Reviews). We are also looping through these reviews according to a few arguments we’ve defined.

Key points of interest:

  • We create a variable ($post_type) for our post type (review)
  • We create a variable ($post_count) for the number of posts we want to display on the page. This uses Block Lab’s block_value() function to retrieve the number set with the 1-5 range field when someone adds the block to their post or page
  • We create a variable ($args) that includes an array of these variables
  • We initiate a new query that uses these arguments
  • We loop through and place our content, with a combination of native WordPress functions and ACF functions, in our HTML markup

Perhaps the most unique part of the above is how we handle our star ratings. If you can’t quite decipher what we’re doing, we are using ACF’s get_field() function and some simple math to determine how many full stars and empty stars we have. We then use a couple of simple for loops to go through these.

That’s it for our main template file. Now for our styling. Remember your CSS will undoubtably be different to ours, but it’s always good to see how other do things. So our CSS template file (movie-reviews/block.css) looks like this:

.reviews {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-gap: 40px;
}
.review {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    height: 500px;
    background-size: cover;
    overflow: hidden;
    border-radius: 6px;
}
.review__title {
    font-size: 18px;
    font-weight: 900;
    display: block;
    letter-spacing: 1px;
    text-transform: uppercase;
}
.review__director {
    font-size: 14px;
    display: block;
    font-weight: 700;
}
.review__score {
    color: gold;
    margin: 10px 0;
    font-size: 20px;
}
.review__content {
    font-size: 16px;
    background: linear-gradient(0deg, rgba(14,34,51,1) 0%, rgba(14,34,51,0.9) 85%, rgba(14,34,51,0) 100%);
    color: #fff;
    padding: 50px 30px 30px ;
    position: absolute;
    top: calc( 100% - 150px);
    height: 100%;
    transition-duration: .1s;
    display: flex;
    flex-direction: column;
    /* justify-content: flex-start; */
}
.review__imdb-link {
    display: block;
    color: #fff;
    border: 1px solid #fff;
    border-radius: 4px;
    padding: 4px 8px;
    align-self: flex-end;
    margin-top: auto;
    font-size: 14px;
    text-decoration: none;
    transition-duration: 0;
}
.review__year {
    margin-bottom: 1em;
}
.review:hover {
    box-shadow: 0px 0px 20px 0px rgba(0,0,0,0.2);
}
.review:hover .review__content {
    top: 0;
    background: rgba(14,34,51,0.9);
    padding: 30px
    /* justify-content: center; */
}
.review__imdb-link:hover {
    background-color: #fff;
    color: rgba(14,34,51,1)
}

Key points of interest here:

  • CSS Grid for layout and positioning
  • Flexbox for content layout within each tile
  • Each tile has overflow set to hidden
  • The content is positioned absolutely within the tile so we can hide some of it outside of the tile
  • On tile hover, the absolutely positioned content slides up

That’s it! Our block is now 100% built and ready to use.

Step 4 – Use the block

Let’s create a new page and add our block. Remember for our block to show anything, you need to have created a few reviews.

On our page, we can see that our block is available to be added:

When added to the page you can see our block form with our number of tiles (range) field:

the-lab.local_wp-admin_post-new.php_post_type=page (5).png

And now click away we get preview mode and can see how it looks in the editor. Nice!

And over on the frontend we get:

Epic!

What else?

There are a heap more things we could do with this block and implementation in general to extend it even further. Such as:

  • Make sure our CSS handles different screen sizes well
  • Write some CSS that improves how the block preview looks in the editor (docs here)
  • Add a block field to select which genre (use a custom taxonomy) of movies should be displayed
  • Add a block field to select which scores (1-5 stars) should be displayed
  • Build a single page template for the review post type so that you can click through to each individual review from the tiles
  • Include TV shows and add another custom taxonomy
  • Automatically retrieve movie posters, directors, and release dates via The Movie DB API

That’s a wrap

This was a good one! We stepped outside of what Block Lab can do on its own and looked at the broader possibilities of what can be done with the wider WordPress ecosystem.

A big thanks as well to Elliot from Advanced Custom Fields who helped me out with this post. Legend!

Any ideas, comments, or feedback? Leave ‘em in the comments. And don’t forget to join The Lab. Our free Slack community for anyone wanting to use the new Block Editor in their custom WordPress work.

Until next time, happy block building.

New Kid on the block?

Subscribe, stay connected, and keep up to date with the latest.

  • This field is for validation purposes and should be left unchanged.

Leave a Reply

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