Building Gutenberg Blocks with Advanced Custom Fields

Tessa Kriesel Reading estimate: 5 minutes

Every person has their favorite set of tools. When we are not able to use those tools to complete a task, the feeling can be overwhelming. What do I do now? How will I accomplish what I need to do? I felt some of these feelings when I heard about Gutenberg, the new WordPress editor. If Gutenberg was block-based, what would happen to my custom page builder I created using Advanced Custom Fields?

Just Released, Pro Users Only

As of May 8th, 2019, this feature is now available for production-ready websites to ACF users with a Pro account. You can learn more about these feature release over at ACF's recent blog post, ACF 5.8.0 Release – PHP Blocks for Gutenberg

Presentation Material

I was pretty excited about this opportunity, so when I saw the first blog post about this future feature, I decided this was something I needed to share with the wider WordPress community. I submitted “Building Gutenberg Blocks with Advanced Custom Fields” to WordCamp Phoenix (and a few others since then, like WordCamp Miami).

It was incredibly well received at WordCamp Phoenix, with many people having the same feelings of fear around how they would continue to use ACF with the new editor. You can watch the presentation over on WordPress.tv and review my slides on SpeakerDeck. I also gave this presentation at WordCamp Miami which you can watch the recording of here.

Let’s Dig In

Let’s dig into the part that you are likely here for, how to actually build the blocks!

To prefix this tutorial, the best place to learn how to do this is in the ACF documentation as they will continue to keep that material up-to-date. This blog post assumes you have ACF PRO 5.8.0 Beta4 or higher installed.

Decide Which Block You Want to Create

First, we need to decide what type of block we want to create. I created a Hero block where you could apply an image background and display content on top of it. I figured this is a pretty straight-forward way to get started and a block that, in my opinion, should be a core block.

Register Your Block

Let’s talk about the functionality that makes the block creation possible. We can use acf_register_block ( $settings );, an array of arguments for registering a block type.

I won’t bring all the settings into this because they will likely evolve and change, so always look for the latest information in the ACF documentation.

You can see in the following Github Gist, that I am registering my Hero block.

Example: (GitHub gist)

/**

* Register hero block

*/

add_action('acf/init', 'hero');

function hero() {

// check function exists

if( function_exists('acf_register_block') ) {

// register a hero block

acf_register_block(array(

'name' => 'hero',

'title' => __('Hero'),

'description' => __('Image background with text & call to action.'),

'render_callback' => 'hero_render_callback',

'category' => 'formatting',

'icon' => 'format-image',

'mode' => 'preview',

'keywords' => array( 'hero', 'image' ),

));

}

}

view rawfunctions.php hosted with ❤ by GitHub

Create Your Field Group

Now that I have registered my block, I can create a field group in my WordPress admin and associate it with the new block I registered.

Build Your Block Markup

Now that we have registered our block & created our ACF field group, it’s time to create the output for how our block will appear. For this example, I will be using the render_callback method — an alternative to this would be the render_template method, where you can put your output in a specific template file.

In the following Gist, lines 46 to 57 probably look pretty familiar to you. We are creating HTML and bringing in our field data where we need it. In lines 31 through 45, we are registering that callback and associating it with our block as well as bringing in my ACF field variables.

Embed: (GitHub gist)

/**

* Register hero block

*/

add_action('acf/init', 'hero');

function hero() {

// check function exists

if( function_exists('acf_register_block') ) {

// register a hero block

acf_register_block(array(

'name' => 'hero',

'title' => __('Hero'),

'description' => __('Image background with text & call to action.'),

'render_callback' => 'hero_render_callback',

'category' => 'formatting',

'icon' => 'format-image',

'mode' => 'preview',

'keywords' => array( 'hero', 'image' ),

));

}

}

/**

* This is the callback that displays the hero block

*

* @param array $block The block settings and attributes.

* @param string $content The block content (emtpy string).

* @param bool $is_preview True during AJAX preview.

*/

function hero_render_callback( $block, $content = '', $is_preview = false ) {

// create id attribute for specific styling

$id = 'hero-' . $block['id'];

// create align class ("alignwide") from block setting ("wide")

$align_class = $block['align'] ? 'align' . $block['align'] : '';

// ACF field variables

$image = get_field('image');

$headline = get_field('headline');

$paragraph = get_field('paragraph');

$cta = get_field('cta');

?>

<section id="<?php echo $id; ?>" class="hero <?php echo $align_class; ?>" style="background-image: url(<?php echo $image; ?>);">

<?php if ( $headline ): ?>

<h2><?php echo $headline; ?></h2>

<?php endif; ?>

<?php if ( $paragraph ): ?>

<p><?php echo $paragraph; ?></p>

<?php endif; ?>

<?php if ( $cta ): ?>

<a class="button" href="<?php echo $cta['url']; ?>" target="<?php echo $cta['target']; ?>"><?php echo $cta['title']; ?></a>

<?php endif; ?>

</section>

<?php

}

view rawfunction.php hosted with ❤ by GitHub

Finished Block

I wrote a small amount of CSS to style the frontend of my block, but other than that, we are done, our block is ready to be used! All of the block code is available in a Github Gist.

Embed: (GitHub gist)

/**

* Register hero block

*/

add_action('acf/init', 'hero');

function hero() {

// check function exists

if( function_exists('acf_register_block') ) {

// register a hero block

acf_register_block(array(

'name' => 'hero',

'title' => __('Hero'),

'description' => __('Image background with text & call to action.'),

'render_callback' => 'hero_render_callback',

'category' => 'formatting',

'icon' => 'format-image',

'mode' => 'preview',

'keywords' => array( 'hero', 'image' ),

));

}

}

/**

* This is the callback that displays the hero block

*

* @param array $block The block settings and attributes.

* @param string $content The block content (emtpy string).

* @param bool $is_preview True during AJAX preview.

*/

function hero_render_callback( $block, $content = '', $is_preview = false ) {

// create id attribute for specific styling

$id = 'hero-' . $block['id'];

// create align class ("alignwide") from block setting ("wide")

$align_class = $block['align'] ? 'align' . $block['align'] : '';

// ACF field variables

$image = get_field('image');

$headline = get_field('headline');

$paragraph = get_field('paragraph');

$cta = get_field('cta');

?>

<section id="<?php echo $id; ?>" class="hero <?php echo $align_class; ?>" style="background-image: url(<?php echo $image; ?>);">

<?php if ( $headline ): ?>

<h2><?php echo $headline; ?></h2>

<?php endif; ?>

<?php if ( $paragraph ): ?>

<p><?php echo $paragraph; ?></p>

<?php endif; ?>

<?php if ( $cta ): ?>

<a class="button" href="<?php echo $cta['url']; ?>" target="<?php echo $cta['target']; ?>"><?php echo $cta['title']; ?></a>

<?php endif; ?>

</section>

<?php

}

view rawfunctions.php hosted with ❤ by GitHub

.hero {

background-attachment: fixed;

background-repeat: no-repeat;

background-size: cover;

background-position: top center;

padding: 100px 0;

color: #fff;

text-align: center;

}

view rawstyle.css hosted with ❤ by GitHub

It’s Your Turn

I hope this post has given you an introductory comfort-level to building Gutenberg blocks with Advanced Custom Fields.

Share

Discover More

Safely Publish to Web from Google Docs with Pantheon Content Publisher

Roland Benedetti (Senior Director, Product) and Zack Rosen (Co-Founder)
Reading estimate: 7 minutes

Unifying Content and Code: Inside Pantheon’s Vision for Content Operations

Chris Yates
Reading estimate: 5 minutes

How Pantheon Protects Your Site from Software Supply Chain Risks in Open Source

Steve Persch
Reading estimate: 8 minutes

Try Pantheon for Free

Join thousands of developers, marketers, and agencies creating magical digital experiences with Pantheon.