An Introduction to Block Templates

Nick Diego Avatar

·

Create a new post or page in WordPress and you’re immediately presented with a blank canvas. This experience can be both empowering and daunting for users. While block patterns go a long way in helping speed up and standardize content creation, being able to present users with a more curated editing experience can be beneficial. Enter block templates.

In this article, you will learn what block templates are, what they aren’t, how to build them, and why you might want to use them on your next project. Let’s get started!

Terminology

Recently an article was posted on this very website titled, An Overview of Block Theme Templates. At first glance, it might seem like a repeat of the article you are reading now. Aren’t “Block Templates” and “Block Theme Templates” the same thing?

The answer is no, but you would be forgiven for thinking otherwise. Terminology in WordPress can get quite tricky, which is why the discussion of block templates must begin with an explanation of what they aren’t.

Theme Templates

Template files are essentially the foundation of every WordPress theme. They determine how content is displayed to users. Traditionally written in PHP, standard theme templates include single.php, page.php, search.php, etc. In block themes, these template files are instead HTML and are comprised entirely of blocks, hence the term “Block Theme Templates.”

Block Templates

Block templates, however, are collections of blocks used to define default initial states within the Editor. These blocks can have predefined attributes and placeholder content, much like block patterns. Admittedly, this definition is a bit confusing and is better illustrated with an example.

Assume you have a website that publishes lots of content with a similar structure: an opening paragraph, table of contents, many sub-sections, etc. You have multiple content creators and need to ensure the format of each post is standardized. You could create a block pattern with these elements predefined that could be inserted into the post. While effective, this requires a user to insert the pattern manually.

What if everything was set up automatically when a new post was created? In other words, what if you could define the default initial state for posts within the Editor? Extrapolate this functionality to custom post types and add locking functionality that limits users’ ability to add or even remove certain blocks. All of a sudden, you have created a curated editing experience!

Implementing Block Templates

Block templates can be created using either JavaScript or PHP. The JavaScript implementation is primarily used in custom block development where templates can be applied to the <InnerBlocks> component. While an interesting topic for discussion, it’s beyond the scope of this article. We will focus solely on PHP and applying block templates to post types.

Posts, pages, and custom post types in WordPress support the template argument. This argument is where you define the block template that should be displayed in the Editor for the given post type. template is defined as an array of blocks, where each item of the array contains both the block name and any applied attributes.

Below is a relatively simple block template that adds a Heading block that’s an H2 with some custom styling, followed by a Paragraph block.

'template' => array(
    array( 'core/heading', array(
        'placeholder' => 'Add Title...',
        'level'       => 2,
        'style'       => array(
            'typography' => array(
                'textTransform' => 'uppercase',
            ),
        ),
    ) ),
    array( 'core/paragraph', array(
        'placeholder' => 'Add Description...',
    ) ),
),
Code language: PHP (php)

As you might have guessed, building out block templates as arrays can quickly get complicated. You also have to know all of the attributes supported by the various blocks and the correct array structure for each. There is a handy workaround using the Pattern block that’s especially useful for more complicated templates.

The Pattern Block “Trick”

While I’m calling this a “trick”, it’s a perfectly valid way to structure a block template and is likely the way most themes will implement this functionality. The idea is that we place our template in a pattern that uses normal HTML block markup allowing us to avoid complicated arrays. The pattern is then pulled into the block template using the Pattern block. The template would look something like this:

'template' => array(
    array( 'core/pattern', array(
        'slug' => 'example-theme/custom-block-template-pattern',
    ) ),
),
Code language: PHP (php)

We are still using an array of blocks to represent the block template; it just happens to be a single Pattern block. The Pattern block is designed for theme development, which allows you to reference a registered block pattern via a slug. In the Editor and frontend, the Pattern block itself will be replaced by the pattern it references.

Block patterns have become synonymous with modern WordPress development, and there are many great resources that show you how to build them, including this video from my recent Builder Basics series. Check out those links if you are unfamiliar with creating patterns.

Now that you know how to define a template argument and the Pattern block workaround, the block template actually has to get implemented. To do so depends on whether the post type already exists or you are registering a new custom post type.

Modifying an Existing Post Type

If you would like to add a block template to an existing post type, such as posts or pages, you will need to modify the post object and add the template argument. We can do this with a few lines of code that should generally be placed in the functions.php file of your theme. Below we have applied the template with our custom block pattern to all posts.

functions.php

/**
 * Register custom block template for posts.
 */
function example_theme_register_posts_block_template() {
    $post_type_object = get_post_type_object( 'post' );
    $post_type_object->template = array( 
        array( 'core/pattern', array(
            'slug' => 'example-theme/custom-block-template-pattern',
        ) )
    );
}
add_action( 'init', 'example_theme_register_posts_block_template' );
Code language: PHP (php)

Registering a New Post Type

Block templates can also be defined during custom post type registration. Below we are registering the post type “books,” and you can see how the template argument is defined along with everything else.

functions.php

/**
 * Register custom block template for books.
 */
function example_theme_register_book_post_type() {
    $args = array(
        'public'       => true,
        'label'        => 'Books',
        'show_in_rest' => true,
        'template'     => array(
            array( 'core/pattern', array(
                'slug' => 'example-theme/custom-block-template-pattern',
            ) ),
        ),
		'hierarchical'  => true,
		'supports'      => array( 'title', 'editor', 'page-attributes' ),
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'example_theme_register_book_post_type' );
Code language: PHP (php)

Template and Block Locking

Controlling the default editing state for post types is powerful, yet users can still move, add, or remove blocks. This can be problematic in certain situations, and template locking allows you to restrict this functionality.

In addition to the template argument, you can specify the template_lock argument, which takes the value all or insert. When set to all, no new blocks can be inserted, and blocks that are part of the block template cannot be moved or removed. When set to insert, no new blocks can be inserted, but existing blocks can move freely and be removed.

In addition to locking the entire template, you can also lock individual blocks. WordPress 6.0 made block locking even easier by exposing it in the Editor UI.

Locking blocks using the Editor UI.
Locking blocks using the Editor UI.

When defining a block template, you can apply the lock attribute to any block. This attribute has two options move and remove. When the options are true, the block cannot be moved or removed respectively. The complete markup on a Paragraph block would look something like this:

<!-- wp:paragraph {"lock":{"move":true,"remove":true}} -->
<p> ... </p>
<!-- /wp:paragraph -->
Code language: HTML, XML (xml)

You can also combine block and template locking depending on your use case. Note that block locking takes precedence over template locking when determining if a block can be moved or removed. We will use block locking extensively in the following example.

Complete Example

Let’s put everything together in a complete example using the Twenty Twenty-Two theme. The goal is to provide a custom block template for the “book” custom post type. We want to present users with a locked set of blocks that allows them to set the book name, author, featured image, book description, and a button link to “Start Reading”. We will use the Pattern block approach as well as block locking. The end result will look something like this:

A simple block template for books.
A simple block template for books.

Since we will use the Pattern block method, we’ll start by registering the block pattern. Twenty Twenty-Two is a block theme, so we can place the pattern file within the patterns/ directory and WordPress will register it for us.

When creating patterns, it’s often best to design them directly in the Editor and copy the block markup into the pattern file. Writing block markup by hand is tedious and prone to error.

The file below is our complete pattern used for the block template. Note that we have restricted this pattern from being displayed in Inserter by setting Inserter: false. We don’t want users to be able to insert this pattern manually. It should only be served by the block pattern for books.

patterns/book-block-template.php

<?php
/**
 * Title: A block template for books
 * Slug: example-theme/book-block-template
 * Inserter: false
 */

?>
<!-- wp:columns {"lock":{"move":true,"remove":true},"align":"wide","style":{"spacing":{"blockGap":"40px"}}} -->
<div class="wp-block-columns alignwide">

<!-- wp:column {"width":"33.33%","lock":{"move":true,"remove":true}} -->
<div class="wp-block-column" style="flex-basis:33.33%">
<!-- wp:post-featured-image {"lock":{"move":true,"remove":true}} /-->
</div>
<!-- /wp:column -->

<!-- wp:column {"width":"66.66%","lock":{"move":true,"remove":true},"style":{"spacing":{"padding":{"top":"40px","right":"40px","bottom":"40px","left":"40px"}}},"backgroundColor":"tertiary"} -->
<div class="wp-block-column has-tertiary-background-color has-background" style="padding-top:40px;padding-right:40px;padding-bottom:40px;padding-left:40px;flex-basis:66.66%">
<!-- wp:group {"lock":{"move":true,"remove":true},"style":{"spacing":{"blockGap":"10px"}}} -->
<div class="wp-block-group">
<!-- wp:post-title {"lock":{"move":true,"remove":true},"fontSize":"x-large"} /-->
<!-- wp:paragraph {"placeholder":"Author Name","lock":{"move":true,"remove":true},"style":{"typography":{"fontStyle":"normal","fontWeight":"500"}},"fontSize":"medium"} -->
<p class="has-medium-font-size" style="font-style:normal;font-weight:500"></p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
<!-- wp:paragraph {"placeholder":"Book Description — Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut sollicitudin finibus mauris, in tincidunt arcu pharetra et. Nulla lorem urna, viverra sed luctus non, hendrerit nec ligula. Nam in mollis turpis. Curabitur tincidunt mollis metus sit amet dictum.","lock":{"move":true,"remove":true}} --
<p></p>
<!-- /wp:paragraph -->
<!-- wp:buttons {"lock":{"move":true,"remove":true}} -->
<div class="wp-block-buttons">
<!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button">Start Reading</a></div>
<!-- /wp:button -->
</div>
<!-- /wp:buttons -->
</div>
<!-- /wp:column -->

</div>
<!-- /wp:columns -->
Code language: HTML, XML (xml)

Next, we must register the custom post type for “book” and apply the pattern as a block template. The code is virtually identical to the example presented above, but we must ensure the pattern slug is set to example-theme/book-block-template.

functions.php

/**
 * Register custom block template for books.
 */
function example_theme_register_book_post_type() {
    $args = array(
        'public'       => true,
        'label'        => 'Books',
        'show_in_rest' => true,
        'template'     => array(
            array( 'core/pattern', array(
                'slug' => 'example-theme/book-block-template',
            ) ),
        ),
		'hierarchical'  => true,
		'supports'      => array( 'title', 'editor', 'page-attributes' ),
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'example_theme_register_book_post_type' );
Code language: PHP (php)

When a user goes to create a new book, they will automatically be presented with the following template. Note that all blocks are locked, which ensures a standardized presentation for each book.

Block template when a user adds a new book.
Block template when a user adds a new book.

Conclusion

While block templates have a fairly narrow application in WordPress development, they are essential when you want to create a curated editing experience for users or when working with specialized custom post types. Hopefully, this article inspired you to start exploring templating and perhaps begin using them on your next project.

As always, external links referenced in this article as well as other related resources are listed below. Stay tuned for more articles on block theming, custom block development, and building with modern WordPress techniques. Until next time!