How to build WordPress patterns

If you’re a theme or plugin developer in the page building ecosystem, now is a better time than ever to start capitalizing on arguably the most exciting addition to Gutenberg, since Gutenberg: patterns.

Let’s dive in and discover how to leverage the new Patterns API and build beautiful patterns.

Recently I published an article on the concept of Block Patterns and how they’re going to make page building in the block editor much more enjoyable. I am still very much in that camp, and I look forward to the introduction of Block Patterns in the upcoming WordPress 5.5 release.

To recap, Block Patterns are predefined block layouts, ready to drop on a page and tweak from there. Once added to a page, the individual blocks of a pattern can be edited in the same fashion as any other block. An important trait of Block Patterns is that once a pattern has been added to a page, it no longer is linked to the original pattern source. The original pattern within the Block Pattern Library may be changed, or even removed, without affecting the Block Pattern added to your page.

Block Patterns can exist both themes and plugins, though I lean towards building them into, or as, a plugin. Using this method, the patterns will still be available whenever the theme is changed. I honestly don’t see a point in tying a pattern to a specific theme, other than the marketability of the theme in question.

Building Block Patterns

Now here’s the meat and potatoes. We’ll be using the Block Pattern API, specifically the register_block_pattern() PHP function. But before we dive into the code, we’ll need to block out the pattern (i.e. design it within the block editor).

Step 1: Blocking the pattern

Block Patterns can technically have as many, or as little, blocks as you’d like. Here’s a pattern I blocked-out as an example:

The idea behind patterns is that a pattern should be something you’d want to repeat throughout your website. So if you’re designing something that’s very one-time-use oriented, it may not make for a great pattern.

Step 2: Copy the block content

Once the pattern has been blocked-out, you’ll need to grab the content of the pattern. For this set of blocks, I’ve selected all the blocks I’d like to make into a pattern, opened the More Menu within the block toolbar, and clicked “Copy”.

Step 3: Register the pattern

Now here’s where we get to leverage register_block_pattern(). This function receives the name of the pattern as the first argument and an array describing properties of the pattern as the second argument. Let’s look at an example:

function tabor_register_block_patterns() {

	if ( class_exists( 'WP_Block_Patterns_Registry' ) ) {

                $content = '<!-- wp:heading {\"align\":\"center\"} -->\n<h2 class=\"has-text-align-center\"><strong>Our approach reflects the people we serve. We are diverse, yet the same.</strong></h2>\n<!-- /wp:heading -->\n\n<!-- wp:buttons {\"align\":\"center\"} -->\n<div class=\"wp-block-buttons aligncenter\"><!-- wp:button {\"borderRadius\":7,\"style\":{\"color\":{\"gradient\":\"linear-gradient(135deg,rgb(0,0,0) 0%,rgb(0,0,0) 50%,rgb(0,0,0) 100%)\"}}} -->\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-background\" style=\"border-radius:7px;background:linear-gradient(135deg,rgb(0,0,0) 0%,rgb(0,0,0) 50%,rgb(0,0,0) 100%)\">Learn More</a></div>\n<!-- /wp:button --></div>\n<!-- /wp:buttons -->\n\n<!-- wp:spacer {\"height\":59} -->\n<div style=\"height:59px\" aria-hidden=\"true\" class=\"wp-block-spacer\"></div>\n<!-- /wp:spacer -->\n\n<!-- wp:gallery {\"ids\":[621,624],\"sizeSlug\":\"full\",\"align\":\"wide\"} -->\n<figure class=\"wp-block-gallery alignwide columns-2 is-cropped\"><ul class=\"blocks-gallery-grid\"><li class=\"blocks-gallery-item\"><figure><img src=\"https://iceberg.test/wp-content/uploads/2020/07/home-image-3.jpg\" alt=\"\" data-id=\"621\" class=\"wp-image-621\"/></figure></li><li class=\"blocks-gallery-item\"><figure><img src=\"https://iceberg.test/wp-content/uploads/2020/07/home-image-2.jpg\" alt=\"\" data-id=\"624\" data-full-url=\"https://iceberg.test/wp-content/uploads/2020/07/home-image-2.jpg\" data-link=\"https://iceberg.test/?attachment_id=624\" class=\"wp-image-624\"/></figure></li></ul></figure>\n<!-- /wp:gallery -->';

		register_block_pattern(
			'tabor/call-to-action-gallery',
			array(
				'title'         => __( 'Call to Action Gallery', 'textdomain' ),
				'description'   => _x( 'A call to action with a beautiful two-column gallery below.', 'Block pattern description', 'textdomain' ),
				'content'       => trim($content),
				'categories'    => array( 'hero' ),
				'keywords'      => array( 'cta' ),
                                'viewportWidth' => 1400,
                                'blockTypes'    => array( 'core/gallery' ),
			)
		);

	}

}
add_action( 'init', 'tabor_register_block_patterns' );

I’ve passed an array with the pattern’s title, description, content (which is the escaped content from step three), keywords (for improved discoverability), a pattern category (for organization), viewportWidth (for how wide the scaled block preview should be displayed at), and blockTypes (for related blocks used by this pattern). Toss this in your theme or plugin and you’ll have a new pattern at your disposal within the block editor. Too easy.

Once added to your theme or plugin, you’ll see the new Block Pattern added to the Patterns Library in WordPress 5.5.  

Step 4: Register additional categories

While Gutenberg provides a few categories out of the box, my new pattern doesn’t quite fit in those defaults. Thankfully, it is quite easy to register an additional category to better organize third-party Block Patterns. The new register_block_pattern_category() function receives the name of the category as its first argument, and an array describing properties of the category as the second argument-i.e. the label.

function tabor_register_block_categories() {
	if ( class_exists( 'WP_Block_Patterns_Registry' ) ) {

		register_block_pattern_category(
			'hero',
			array( 'label' => _x( 'Hero', 'Block pattern category', 'textdomain' ) )
		);

	}
}
add_action( 'init', 'tabor_register_block_categories' );

And that’s it. The new category displays along the others, though it will be appended to the bottom of the list. I do think a welcome fast-follow to the Patterns Library is to make the categories alphabetically ordered, regardless of source.

A closer look at blockTypes

I recently updated this post to reference the newly added blockTypes object, which patterns can leverage to display as a suggested pattern for a specific block. As of WordPress 5.8, patterns that declare associated blocks will show up in the new UI when a block is added to a page, like this:

The one catch is that patterns must include associated blocks. I.e. you can’t just suggest a gallery pattern for the Social Links block — you need to actually use the core/social-links block in the pattern.

This is an interesting way to leverage patterns throughout the editor, but I’m not 100% sold on it just yet.

Iterating on patterns

Block Patterns will make page building in the block editor much more streamlined, but there are a few improvements I’d like to see iterated upon. For one, better categorization/organization. Block Patterns aren’t clearly distinguishable and aren’t really categorized. Perusing the library in its current state is not quite productive. The only discoverability methods are searching and scrolling through the single column list of patterns.

The categories are almost invisible, and there’s no way to sort or filter patterns – which I think would be helpful. A while back, I suggested a modal interaction for patterns, which I believe would lead to improved pattern discovery, perhaps with a categorized or filtering sidebar of sorts. Having a solid method to categorize and a more efficient way to browse will only help folks build pages faster and with more confidence.

Second, I would like to see a way for users to save a set of blocks as a Block Pattern, much like saving a Reusable block. Gutenberg aims to lower the technical barrier of publishing content-rich pages within WordPress, so naturally we should aim to reduce the technical effort it takes to make Block Patterns. In all though, I’m all for Block Patterns, and I look forward to seeing the creative ways folks leverage patterns to improve page building in the block editor.

Are you planning on adding patterns to your theme or plugin?

Responses

  1. Jeremy Techtmann Avatar
    Jeremy Techtmann

    I have already started using block patterns and I am really excited for them. In many cases I think they will replace building custom blocks.

    Adding an extra defining class to them when pasted into the function then allows me to style them as I wish. Not to mention they can be both locked or unlocked to allow the client, depending on comfort and ability, to edit them once on the page or not.

  2. Thomas Weichselbaumer Avatar

    Hi Rich,

    Thanks so much for your tutorial about the Block Pattern API, very helpful.

    I do not agree with you about patterns belonging mostly into plugins though 🙂
    I think themes are the perfect place for patterns, since layout is primarly a task for themes, not plugins (that only changed with page builders). Why should theme shops create extra plugins to hold patterns instead of adding them to themes directly?

    Block patterns will allow users to re-create the theme demo with just a few clicks and theme authors don’t have to build extensive layout options or integrate with page builder plugins anymore. It really is a game changer for the painful theme setup process.

    And you’re spot on about the organization of patterns. I don’t understand why it was jammed into the small sidebar area, without a way to browse categories.

    Cheers,
    Thomas

  3. Cathy Tibbles Avatar

    Yes!! Thank you. This will make page building so much easier for clients where we have custom blocks, but putting them together is tedius!

  4. Ryan Peacan Avatar

    Thanks for this post! I feel like clients are going to love this feature. One thing I can’t figure out is how to disable WordPress’ default patters, however.

  5. Dennis Avatar

    Really exciting feature, for which I see much possibilities. Even more when some future improvements are implemented (categories, usability).

    There was one thing I was wondering: Why has the “content” attribute to be filled with raw html? Couldn’t this be much easier with object notation like in InnerBlocks e. g.?

  6. Per Thykjaer Jensen Avatar

    Thank you for a very clear and easy readable introduction to the subject. I will definitely teach building reusable blocks in my multimedia design classes. It’s a cool feature.

    BTW I also think that a plugin is a better choice than in the theme. If you change to another theme the plugin will still be available.

  7. Dumitru Brinzan Avatar

    Thank you for this easy-to-follow guide.
    One question though, about this particular sentence:

    “I’ve passed an array with the pattern’s title, description, content (which is the escaped content from step three), keywords (for improved discoverability), and a pattern category.”

    I don’t see anything in the code that refers to keywords. Have you modified some original code that previously had keywords?

    Thank you.

  8. Dan Stramer Avatar
    Dan Stramer

    Can block patterns be used as page templates?
    What I mean is, after creating the block pattern, let’s say you used it on 5 different pages on the site. Now you would want to add a block to the pattern, can it be updated across all the pattern you used in the existing pages? Like a page template that once you change the php there, it will change across all pages who use that template.
    Hope I was clear 🙂
    Thanks
    Dan

  9. Raphaël Avatar

    You don’t need to escape, you could also use PHP heredoc / nowdoc:
    “““`
    ‘content’ => <<<'EOF'

    EOF
    `

  10. Rafael Belvederese Avatar
    Rafael Belvederese

    Instead of escaping/unescaping, you could just use a heredoc string: https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.heredoc

    Your example would become:
    function tabor_register_block_patterns() {

    if ( class_exists( ‘WP_Block_Patterns_Registry’ ) ) {
    $content = HTML<<<

    Our approach reflects the people we serve. We are diverse, yet the same.



    Learn More


    HTML;

    register_block_pattern(
    ‘tabor/call-to-action-gallery’,
    array(
    ‘title’ => __( ‘Call to Action Gallery’, ‘textdomain’ ),
    ‘description’ => _x( ‘A call to action with a beautiful two-column gallery below.’, ‘Block pattern description’, ‘textdomain’ ),
    ‘content’ => $content,
    ‘categories’ => array( ‘hero’ ),
    )
    );

    }

    }
    add_action( ‘init’, ‘tabor_register_block_patterns’ );

Leave a Reply to Dan Stramer Cancel

Your email address will not be published. Required fields are marked *

You may also enjoy…