Skip to content

Michael LaRoy - Home

WordPress ACF Blocks... but Statamic


One of the reasons I wanted to start building with Statamic was the relative simplicity in making complex blocks on the page. In WordPress land, the complexities of building Blocks forces us out of the PHP templates and into JavaScript with React; unless, of course, we opt for using ACF for creating blocks.

Even then, the boilerplate setup to get custom ACF blocks working is anything but simple. Check out this post to see my implementation. There you can see how much stuff you need:

  • a json file to define your block
  • some PHP to loop through the json files and register them
  • even more PHP for the actual block template.

And this is all before even defining any fields in ACF.

This isn’t to say that there isn’t any setup for achieving something like this with Statamic. However, we get all of the ACF-style fields out of the box (no paying monthly for ACF Pro), and we can define our them in the UI. We can also define our “blocks” in the UI, in a couple of different paradigms.

Statamic Sets

The first way we can do this is by using ”sets,” which are part of the Bard fieldtype. You can think of these as sort of “inner blocks” for your content area, where the Bard field is akin to the WP the_content which contains all of the page’s content as blocks.

These sets, however, wouldn’t be page-level blocks, but rather sets of content that can be injected into the main content area of the page, for example. Even the UI is similar, where we get a little ”+” icon in between paragraphs of text if we want to inject a set into the content editor.

statamic bard screenshot
Source: Statamic Docs

Here, the “bard field” is being used as the main content field for our blog post. Not too much going on, as we’re just rendering the content:

<!-- blog/show.antlers.html -->
<article>
    <div class="prose">
        {{ bard_field }}
    </div>
</article>

However, once we define some sets, our template will need to change, because we’re no longer outputting a string of HTML, but an array of data which includes our sets:

<!-- blog/show.antlers.html -->
<article>
    <div class="prose">
        {{ bard_field }}
            {{ partial src="sets/{type}" }}
        {{ /bard_field }}
    </div>
</article>

In this case, the opening/closing tags act as a sort of loop, where with each iteration it finds the appropriate template for the current set “type”: the inner part of the Antlers template looks for our resources/views/partials/sets/<type>.antlers.html file, which contains the template logic for that particular Set. Note, if we opt to do this, the default non-set content will be defined as “text,” which will be treated as a set and need its own template.

This could also be done with a if/else condition in place, instead of abstracting away into template partials. I prefer the partials, just in case you start to get too many sets, which would make for a lenghty template:

<!-- blog/show.antlers.html -->
<article>
    <div class="prose">
        {{ bard_field }}
            <!-- "text" is the default type, the actual non-set content -->
            {{ if type == "text" }}
                <div class="text">
                    {{ text }}
                </div>
            {{ elseif type == "hero_image" }}
                <div class="heroimage">
                    <img src="{{ hero_image }}" alt="{{ caption }}" />
                </div>
            {{ /if }}
        {{ /bard_field }}
    </div>
</article>

Statamic Replicator Fieldtype

The second way we can define our blocks is by using a Replicator fieldtype. We can leverage the Replicator in a similar manner to which we might have used ACF with WordPress pre-Block Editor using the “flexibile content” field, which is essentially a glorified repeater.

statamic replicator screenshot
Source: Statamic Docs

For example, we might create a field called “Page Builder,” which is of the Replicator fieldtype. This replicator, like the Bard fieldtype, lets us define custom “sets” that we can use to create our top-level content blocks. One of these blocks could even have that Bard fieldtype, with its own sets, but that’s a bit inception-y for the moment. I digress…

Inception

The default layout for our page that uses this could look like this:

<!-- default.antlers.html -->
{{ page_builder scope="block" }}
    {{ partial src="page_builder/{type}" }}
{{ /page_builder }}

Just like the Sets above, the page builder would look for the resources/views/page_builder/<type>.antlers.html file corresponding to the current Set for this Replicator. First, it would leverage a higher-level _block.antlers.html template (note the “scope” prop), so that we could wrap each one in the same HTML if we wanted to:

<!-- /page_builder/_block.antlers.html -->
<section class="{{ class }}">
    {{ slot }}
</section>

Then, inside the slot is where the actual template would be rendered, just like with our Bard Sets. In this way, we create a whole bunch of Sets for building out our page.

Repeat Yourself

The WordPress way of doing blocks, with our without ACF, has its advantages and disadvantages. For me, the Statamic way makes it easier for both content editors and developers to be effective in their efforts to build a robust website.

Here, we have less boilerplate setup code, and can focus on what really matters: the actual template code, and an easy interface to add blocks to the page. We don’t need to mess with InnerBlocks, and can easily separate out the Page builder blocks from the content sets.

Easy peasy.

Easy peasy lemon squeezy


If you want to see some examples of Sets that I am using in my Starter Kit, try these articles out to start:

5 Accessibility Fixes You Can Make Today

Learn about the most common reasons that websites fail accessibility standards, and what you can do about it.