DEV Community

matiasautio
matiasautio

Posted on

How to create Gutenberg blocks using Advanced Custom Fields in WordPress

This tutorial assumes you have a block theme (like Twenty Twenty-Three) and the ACF plugin installed.

Our objective is to create a simple Testimonial block with customisable text, image, text colour and background colour using Advanced Custom Fields.

End result

1. Register a Block

First you have to create a JSON file to with the necessary information about the block.

Documentation for all the metadata options inside block.json

blocks/testimonial/block.json

{
  "name": "acf/testimonial",
  "title": "Testimonial",
  "description": "A custom testimonial block.",
  "style": ["file:./testimonial.css"],
  "category": "formatting",
  "icon": "admin-comments",
  "keywords": ["testimonial", "quote"],
  "acf": {
    "mode": "preview",
    "renderTemplate": "testimonial.php"
  },
  "supports": {
    "align": "false"
  }
}
Enter fullscreen mode Exit fullscreen mode

Most of the fields are quite self-explanatory, like name, title and description. Here we are using style property to assign a stylesheet for this block. You could also use a global stylesheet here. The only ACF specific fields are mode and renderTemplate. We also want to disable align for this block.

Register the block with WordPress function register_block_type in functions.php or equivalent.

functions.php

add_action( 'init', 'register_acf_blocks' );
function register_acf_blocks() {
    register_block_type( __DIR__ . '/blocks/testimonial' );
}
Enter fullscreen mode Exit fullscreen mode

2. Create a Field Group in ACF

In WordPress Admin, create a new field in Custom Fields > Add New with the following fields.

Creating a field group in ACF

Remember to configure the location rule also so that the block shows up correctly in the editor.

3. Render the block

We need to create a PHP file with a name that matches the render_template setting inside the block.json we created in step 1.

blocks/testimonial/testimonial.php

<?php

/**
 * Testimonial Block Template.
 *
 * @param   array $block The block settings and attributes.
 * @param   string $content The block inner HTML (empty).
 * @param   bool $is_preview True during backend preview render.
 * @param   int $post_id The post ID the block is rendering content against.
 *          This is either the post ID currently being displayed inside a query loop,
 *          or the post ID of the post hosting this block.
 * @param   array $context The context provided to the block by the post or it's parent block.
 */


// Load values and assign defaults.
$text             = get_field('testimonial') ?: 'Your testimonial here...';
$author           = get_field('author') ?: 'Author name';
$image            = get_field('avatar') ?: null;
$background_color = get_field('background_color') ?: '';
$text_color       = get_field('color') ?: '';

// Build a valid style attribute for background and text colors.
$styles = array('background-color: ' . $background_color, 'color: ' . $text_color);
$style  = implode('; ', $styles);

?>
<div class="testimonial-block" style="<?php echo esc_attr($style); ?>">
    <blockquote class="testimonial-blockquote">
        <p class="testimonial-text"><?php echo esc_html($text); ?></span>
        <p class="testimonial-author"><?php echo esc_html($author); ?></span>
    </blockquote>
    <div class="testimonial-image">
        <?php if ($image) : ?>
            <?php echo wp_get_attachment_image($image['id'], 'full'); ?>
        <?php endif; ?>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

In the template we first load the values from all the fields using get_field(). Then we get the styles from the color pickers and output them as inline styles. Finally we create the block html and echo the values.

4. Create the stylesheet for the block

Finally, let's create a basic stylesheet for our shiny new block using CSS Grid.
blocks/testimonial/testimonial.css

.testimonial-block{
    display: grid;
    grid-template-columns: 1fr 200px;
    padding: 1rem;
}

.testimonial-image img{
    max-width: 100%;
    aspect-ratio: 1/1;
    width: 100%;
    height: auto;
    border-radius: 9999px;
    object-fit: cover;
}
Enter fullscreen mode Exit fullscreen mode

Done!

Further reading:

Top comments (0)