The best way to use WordPress Gutenberg Block Editor

Getting the balance right: Making the most of WordPress’ block editing experience

WordPress released the Gutenberg block editor in late 2018 and since that time we’ve learned a lot about what does—or doesn’t—work when it comes to building custom blocks.

At The Code Company, we have worked on many new digital publishing site builds and migrations of existing websites sites using the WordPress Gutenberg editor. This specialist media industry experience has enabled us to create a winning block building strategy.

This article will predominantly focus on using Gutenberg as an article editor and incorporating the customisations that often arise in custom editorial workflows.

Advanced Custom Fields (ACF) Blocks for Gutenberg

Our initial approach was to use ACF Blocks. Rather than building custom Gutenberg blocks with React, etc, ACF blocks allow you to build custom blocks using ACF fields and a relatively simple PHP-based template.

This made a lot of sense for us because:

  • We were already very experienced with ACF as we have been using it for many years for custom theme builds, applications and the like. Using ACF blocks means we can leverage our existing knowledge base for this new technology.
  • It is much more time efficient to work with over building out native Gutenberg blocks in React (etc). We get access to ACF’s huge selection of field types and we can build out templates using familiar PHP/HTML with all the typical ACF APIs, get_field() etc.

So it sounds like a perfect fit – right? We get the benefits of using a stable technology that we have a lot of experience with. And it is more time and cost effective.

Not quite, unfortunately.

ACF blocks are a great tool for developers, however, we discovered rather quickly that there are some user experience issues that accompany this approach.

The main problem is that the ACF UI is very different from the native Gutenberg experience. Typically native Gutenberg blocks are edited inline in a ‘what you see is what you get’ (WYSIWYG) fashion. This also includes some additional controls in the sidebar to tweak things like background colours etc. ACF blocks are edited entirely with ACF fields in the sidebar; there is no WYSIWYG editor — only a preview.

This is fine for simple / small blocks, but the bigger and more complex they get the more confusing and convoluted they become. This can get to the point that the user experience is worse than the flexible layouts we were using.

For example:

When ACF blocks are combined with native blocks, it can get even more confusing for users. You end up with two very different UIs when editing content.

A Better Approach to Gutenberg in WordPress

There is a better way. And it involves building some custom Gutenberg blocks (native ones, not with ACF!).

Taking a step back, we realised much of what we were building with ACF blocks was layout-related. We would have one ACF block for each row in a template. For instance, we might have a three column layout for testimonials built as a single block. There are three testimonials, each with a testimonial quote, the person’s name and a link, which means there nine separate fields for this very simple block/row.

A smarter approach to building this testimonial block is to decouple the three column layout part from the testimonial part. That way each of the testimonials can be edited individually. It also means we can easily change it to a four column testimonial row if desired without the need to create an entirely new ACF block for it. Better all around!

How to Build Layouts in Gutenberg using InnerBlocks

Gutenberg actually makes this really easy to implement as it provides a component called `InnerBlocks`. `InnerBlocks` allows us to nest/embed blocks within our blocks, which can be very powerful for building layouts.

For example, to build our testimonials layout, we might do something like this:

<div className={props.className}>
  <InnerBlocks
    templateLock="insert"
    template={[["tcc/testimonial"], ["tcc/testimonial"], ["tcc/testimonial"]]}
  />
</div>

When this block is added to the editor, it will automatically create a three nested tcc/testimonial blocks as per the template we set. It will also be locked to just three columns as we are telling it to prevent inserts / deleted with the templateLock="insert" parameter.

Assuming `tcc/testimonial` is a custom block for a single testimonial, a user could easily edit each of the separate testimonials in this layout. They would only have three fields (at most) to deal with at any given time. So it’s much simpler.

We may even choose to build the `tcc/testimonial` block using ACF. Any UX issues would be isolated to the self contained block and it would likely be much easier, quicker and cheaper to build and maintain over a custom block.

Reusable Layout Gutenberg Blocks

There is a more powerful way to use layouts like these as well, if we generalise a bit. Rather than having the layout restricted to just the `tcc/testimonial` block, we can open this up and allow any kind of block to be embedded. Then we have a reusable three column layout that can be used for anything, not just testimonials.

The way we do this is to have a general “column” block that we use in the template, like so:

<div className={props.className}>
  <InnerBlocks
    allowedBlocks={["tcc/column"]}
    templateLock="insert"
    template={[["tcc/column"], ["tcc/column"], ["tcc/column"]]}
  />
</div>

We would then have a very basic tcc/column block, which looks something like this:

<div className={props.className}>
  <InnerBlocks templateLock={false} allowedBlocks={"*"} />
</div>

If we add a three column layout into the block editor, we get three columns that can host any content. This content could also be more than one block. For example, you could manually build out the testimonials in the editor using this set up. You might add a quote block followed by a paragraph for the person’s name / link into each of the columns.

This is very similar to Gutenberg’s built-in columns block, however, building out custom layout blocks in this way gives us much more flexibility. It’s rare that we just want some columns as set out in the example above as usually there are other requirements. A common example of this might be setting a background video or the like.

Final Thoughts on our Gutenberg Strategy

It’s important to understand that WordPress Gutenberg is not a replacement for a page builder. Though we do use it to build out pages, it is primarily designed for (and best suited to) posting content. There are times when we decide Gutenberg is a better fit, but we assess that on a case by case basis. As with most publishing challenges, it all comes down to the client’s requirements.

When it comes to user experience and flexibility, page builders win over Gutenberg. It is much more time and cost effective for most publishers to build a landing page using a page builder (which would likely take a couple hours) rather than paying developers to build out custom templates / blocks for everything.

On that note, our preference in the page builder space is Beaver Builder. We find it has the least overheads and is the easiest to work with from both a developer and an end user perspective.

When comes to deciding on the best publishing tool, our philosophy is simple: A page builder is best suited for landing / marketing pages, Gutenberg for everything else.

Zac Scott

Zac was a former Head of Engineering at The Code Company. He worked with our engineering team heavily to ensure coding standards and best practices are followed. Zac has a history of complex functionality and data heavy projects.