Introduction
Included in ACF PRO is a powerful PHP-based framework for developing custom block types.
ACF blocks are highly customisable and powerfully dynamic. They integrate deeply with custom fields allowing PHP developers to create bespoke solutions inline with WordPress theme development.
Features
🌎 PHP Environment
ACF blocks is a PHP framework and does not require any JavaScript. This differentiates itself from the WordPress block API which relies heavily on modern JavaScript techniques, syntax and build tools.
🎨 Simple Templating
Similar to WP theme development, ACF blocks are rendered using a PHP template file or callback function allowing full control over the output HTML.
🔌 Custom Fields Compatible
ACF blocks offer full compatibility with all field types including both the Repeater and Clone fields!
It’s a similar story for template functions too. Whether you are loading a field value via get_field()
, or looping over a Repeater field using have_rows()
, the experience remains familiar and consistent to regular theme development.
👀 Live Previews
Content changes, and so do block previews! When editing an ACF block, the HTML will update in the backend giving you a real time preview of your content. If you use an ACF block in a Query Loop block or in a Full Site Editing Block Theme, your block preview will automatically update as your query changes.
🌈 Native Compatibility
Believe it or not, ACF blocks maintain native compatibility with WordPress core. This allows features such as “alignment”, “anchor” and “re-usable blocks” to work!
🎉 Anywhere and everywhere
ACF blocks are not tied to metadata, meaning they can be used anywhere in Gutenberg, and multiple times per post.
Requirements
ACF Blocks is a premium feature found in ACF PRO version 5.8.0 and above. If not already, please consider upgrading to take advantage of this premium feature! ACF PRO version 6.0.0 introduced even more features and a new modernized registration system that matches current WordPress practice, bringing ACF blocks even closer to native WordPress blocks. For this new method of block registration, you need WordPress 5.8 (or WordPress 6.0, if you want to store your ACF Blocks inside a theme)
Key Concepts
Before reading any further, it’s a good idea to familiarize yourself with some of the concepts introduced by the Gutenberg editor.
- Blocks are an abstract unit for organizing and composing content introduced in WordPress 5.0. If it helps, you can think of blocks as a more graceful shortcode, with rich formatting tools for users to compose content.
- Blocks can be static or dynamic. ACF Blocks are dynamic, meaning they are rendered server-side and allow for PHP logic.
- ACF Blocks are registered and customized within the
functions.php
file using PHP and do not require any knowledge of React or the WP blocks JavaScript API. - ACF blocks differ from WP blocks in that the data is decoupled from the design. This allows for faster development of blocks by focusing only on the HTML output.
- Block data is saved within the “post_content” as an HTML comment. This makes them unique to metaboxes which save data to the “postmeta” table.
Getting Started
The ACF Blocks framework performs a lot of “magic” behind the scenes to offer an intuitive development experience. We’ve simplified the process down to just three steps:
1. Register a Block
In ACF PRO 6.0, block.json became the recommended way of registering blocks – matching the native WordPress registration methods. This requires WordPress 5.8+. If you’re on an earlier version of ACF or WordPress, you can continue to use the previous function: acf_register_block_type()
Block.json blocks store block metadata inside a “block.json” file inside your plugin, or since WordPress 6.0, your theme. This makes blocks much more portable, and easier to share between projects.
💡 This example only uses a small handful of the available settings so please be sure to read the block.json ACF configuration doc for a full list, along with WordPress’s block.json documentation.
Here’s an example block.json configuration object, we’re storing this in blocks/testimonial/block.json
in our theme or plugin:
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"
},
"align": "full"
}
Aside from the ACF key, everything else in a block.json file is native WordPress configuration.
Once you’ve got your block.json file, you need to add some PHP to register it with the WordPress function register_block_type. You can either put this in your plugin’s PHP file, or in your theme’s functions.php file or equivalent:
add_action( 'init', 'register_acf_blocks' );
function register_acf_blocks() {
register_block_type( __DIR__ . '/blocks/testimonial' );
}
2. Create a Field Group
The next step is to create a field group for your block. Note that any and all ACF fields can be used within your block – there are no limitations!
That said, we don’t recommend using complex or large amounts of fields. Keep your blocks as lightweight and simple as possible.
From the location rules, use the “Block” rule to select your newly registered block type.
3. Render the Block
Lastly, you’ll need to tell ACF how to render the block, which is essentially the same process you’re used to for displaying custom fields.
This is done by creating a template file within your theme that matches the render_template setting used when registering the block. In this example, the template file will be called ‘blocks/testimonial/testimonial.php’.
💡 There are multiple ways to render a block. Please read the ACF block.json configuration docs for a full description on the render_template and render_callback configuration keys inside the ACF object..
One very exciting feature of ACF Blocks is that all the ACF API function such as get_field()
, the_field()
and have_rows()
will work as expected!
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.
*/
// Support custom "anchor" values.
$anchor = '';
if ( ! empty( $block['anchor'] ) ) {
$anchor = 'id="' . esc_attr( $block['anchor'] ) . '" ';
}
// Create class attribute allowing for custom "className" and "align" values.
$class_name = 'testimonial-block';
if ( ! empty( $block['className'] ) ) {
$class_name .= ' ' . $block['className'];
}
if ( ! empty( $block['align'] ) ) {
$class_name .= ' align' . $block['align'];
}
// Load values and assign defaults.
$text = get_field( 'testimonial' ) ?: 'Your testimonial here...';
$author = get_field( 'author' ) ?: 'Author name';
$author_role = get_field( 'role' ) ?: 'Author role';
$image = get_field( 'image' ) ?: 295;
$background_color = get_field( 'background_color' );
$text_color = get_field( 'text_color' );
// Build a valid style attribute for background and text colors.
$styles = array( 'background-color: ' . $background_color, 'color: ' . $text_color );
$style = implode( '; ', $styles );
?>
<div <?php echo $anchor; ?>class="<?php echo esc_attr( $class_name ); ?>" style="<?php echo esc_attr( $style ); ?>">
<blockquote class="testimonial-blockquote">
<span class="testimonial-text"><?php echo esc_html( $text ); ?></span>
<span class="testimonial-author"><?php echo esc_html( $author ); ?></span>
<span class="testimonial-role"><?php echo esc_html( $author_role ); ?></span>
</blockquote>
<div class="testimonial-image">
<?php echo wp_get_attachment_image( $image, 'full' ); ?>
</div>
</div>
You’ll note that our block.json includes a stylesheet. The format of this in our example is called a WPDefinedAsset. You can also pass a style handle which has already been registered by wp_register_style()
– but you must have registered this style before your block registration. For further details on registering scripts and styles for blocks, please check our What’s new with ACF Blocks in ACF 6 documentation.
Demonstration
That’s all there is to it! You can immediately start using your new block within Gutenberg and place it anywhere within your content 💯.
FAQ
$post_id
parameter from working as expected in our template functions. If you really need to, you can load the post_content of a given post, and then parse the blocks using the parse_blocks()
function but we do not recommend this for performance reasons.