The default WordPress editor is fine for simple pages but when looking for more complex layouts, it lacks flexibility and for a web designer, this can be frustrating. I could use a code block but it’s not very professional when it’s for a client who doesn’t know anything about HTML.
The ACF (Advanced Custom Fields) plugin brings the WP editor to a whole new level by allowing you to create your own blocks that meet your requirements. Note that the block feature is only available in the PRO version. Let’s look at a simple example.
Register Your ACF Block
The first thing we need to do is register our custom block. For this tutorial, we’re going to create a “Testimonials” block. Go to your functions.php
file and add the following function:
add_action('acf/init', 'acf_init_custom_block_types');
function acf_init_custom_block_types() {
// Check function exists.
if( function_exists('acf_register_block_type') ) {
// Register block.
acf_register_block_type(array(
'name' => 'testimonials',
'title' => __('Testimonials'),
'description' => __('Display Testimonials block'),
'render_callback' => 'acf_block_render_testimonials',
'category' => 'formatting',
'icon' => 'admin-comments',
'keywords' => array( 'testimonial', 'quote' ),
));
}
}
I’m using render_callback
to call a function named acf_block_render_product_offer
and from there I will be able to have all the logic code separated from the HTML as you’ll see a bit later. But you can also use render_template
and directly call a template part file instead.
'render_template' => 'template-parts/blocks/product-offer.php',
Creating Custom Fields
Creating the fields is very simple. In your WordPress admin backend, go to “Custome Fields” and click on “Add New” to create a new field group. At the top, type a descriptive name, so in our case, it could be “Testimonials Block”. Then next we’re going to create our first field with a type of “Repeater”.
The “Repeater” field type will allow us to have multiple testimonials in the same block.
Now, in the “Sub Fields” section, we need to create all the fields that we will use in each testimonial.
And the last important thing to do on this page is to choose where we want our fields to display in the “Location” section. Select the Testimonials block we registered and then press “Publish” to save everything.
Adding The Block To A Post
Now, create a new page, and you should be able to see the “Testimonials” in the list of blocks. Add it to your editor, create as many testimonials as you want, fill in the fields, and publish.
Getting The Data From The Fields
In part 1, we registered the block and set render_callback
to call a function acf_block_render_product_offer
. It’s now time to create this function where we set a unique ID, our classes, and loop through every row we’ve created in the backend. In the loop, we also include our template part to display the actual testimonials. In your functions.php
file, add the following code:
function acf_block_render_testimonials($block){
// Create block ID
$id = $block['anchor'] ?? 'testimonial-' . $block['id'];
// Create class attribute allowing for custom "className" values
$className = ' testimonials-block';
if( !empty($block['className']) ) {
$className .= ' ' . $block['className'];
}
// Check rows have been created
if( have_rows('testimonials') ) {
// Loop through rows
echo '<div class="'. $className .'" id="'. $id .'">';
while( have_rows('testimonials') ) { the_row();
// Get the values
$image = get_sub_field('author_image') ?: 'default-image.jpg';
$text = get_sub_field('author_testimonail');
$name = get_sub_field('author_name');
$role = get_sub_field('author_role');
// Include template part
include get_stylesheet_directory() . '/template-parts/blocks/testimonial.php';
}
echo '</div>';
}
}
Displaying The Rows
Now is the time to build the layout of our testimonials which is pretty simple.
<div class="testimonial-item">
<img src="<?php echo $image; ?>" alt="Author picture" />
<div class="quote">"<?php echo $text; ?>"</div>
<div class="author-name"><?php echo $name; ?></div>
<div class="author-role"><?php echo $role; ?></div>
</div>
Here is the result:
It’s very simple but here is the CSS I’ve used for the design if you are interested.
.testimonials-block {
display: grid;
text-align: center;
grid-template-columns: repeat(3, 1fr);
gap: 40px;
}
.testimonials-block .testimonial-item {
display: flex;
flex-direction: column;
align-items: center;
}
.testimonials-block img {
width: 100%;
border-radius: 100%;
max-width: 200px;
}
.testimonials-block .quote {
max-width: 250px;
font-weight: 600;
font-style: italic;
font-size: 1.7rem;
line-height: 20px;
margin: 12px 0;
}
.testimonials-block .author-name {
line-height: 14px;
font-weight: 600;
border-top: 1px solid #ccc;
padding-top: 12px;
}
.testimonials-block .author-role {
font-size: 1.2rem;
}