Home › Block and Plugin Tutorials › Block Editor › What Are Block Patterns – A Detailed Breakdown
What Are Block Patterns – A Detailed Breakdown
In the ever-evolving landscape of WordPress, block patterns have emerged as indispensable tools for enhancing productivity and design consistency. These reusable templates, composed of HTML code from one or multiple blocks, allow users to streamline their content creation process.
As an author of a pattern plugin called Pattern Wrangler, I’ve taken a deep dive into how patterns work within WordPress. I’m here to share what I’ve learned and to answer your questions about patterns. This is a technical deep-dive with lots to cover. Let’s get started.
Table of Contents
- Introduction – What are block patterns?
- How the Pattern Library is populated
- Registering block patterns
- Creating local patterns using synced and unsynced patterns
- How to get your pattern library under control
- Conclusion
Introduction – What are block patterns?
A pattern is the raw HTML code of one or more blocks saved to be re-used later. These patterns can then be inserted into the WordPress block editor via a Pattern browser or slash command.
Behind every block sits some HTML code that describes the block and its attributes. For example, a normal quotes block would look like this:
<!-- wp:quote -->
<blockquote class="wp-block-quote"><!-- wp:paragraph -->
<p>This is a quote.</p>
<!-- /wp:paragraph --><cite> - Me</cite></blockquote>
<!-- /wp:quote -->Code language: HTML, XML (xml)You can take the above code and paste it into the block editor, and it’ll render as a paragraph block. This code, when saved for reuse, is a block pattern.
Pasting a Quote into the Block Editor
When you copy a block or group of blocks, you are copying the pattern’s code to your clipboard. You can then easily paste your clipboard contents in another area of the block editor for an exact duplicate.
This speed in which a pattern can be copied, pasted, and stored for later is a huge strength of the block editor. For example, a section of card blocks can be saved as a pattern, and inserted everywhere there needs to be a card design. This saves you from having to re-create the design every time.
As nice as patterns are, they can be a mystery. For example, how is the Patterns view populated? How do they work?
Patterns View in the Block Editor
Within this guide I will go over in detail:
- How the pattern library is populated.
- How to register your own patterns.
- How to create local patterns using synced and unsynced patterns.
- How to get your pattern library under control.
How the Pattern Library is populated
The Pattern Library represents all of the registered patterns on your site, merging all pattern sources together.
To access the Pattern Library, you would use the block inserter (+) in the block editor and navigate to the Patterns column. From there, you can insert a pattern.
The Pattern Library, or collection of all your site patterns, is populated from three main sources:
Patterns come from Remote, Local, and Registered Patterns
- Remote Patterns: These are patterns that come from the online Block Pattern Directory. These can be loaded by Core WordPress, as well as by the theme.
- Local Patterns: These are patterns stored as a post type in your database.
- Registered Patterns: These are patterns that are programmatically registered via a plugin, theme, or Core. The pattern is typically hard-coded or created as a separate file. In the case of Remote patterns, these are loaded in remotely and then registered.
Remote patterns
Remote patterns come from the online Block Pattern Directory.
WordPress Pattern Directory
When WordPress loads, it tries to load remote patterns from three areas:
- Load remote patterns from the Pattern Directory marked with the
corekeyword. - Load remote featured patterns from the Pattern Directory with the
featuredcategory. - Load any remote patterns the theme would like included via
theme.jsonsupport.
Remote Patterns Come From Three Sources
Core remote patterns
For a theme to support Core patterns, the theme has to declare support via add_theme_support:
add_theme_support( 'core-block-patterns' );Code language: PHP (php)Patterns Screen Showing Remote Core Patterns
Core patterns load remote patterns with the core keyword. These are registered in WordPress with the pattern source as pattern-directory/core.
Core “featured” patterns load remote patterns using the featured category from the Pattern Directory. These featured patterns are registered with source as: pattern-directory/featured.
Core patterns can clutter up a normal Patterns interface, so unless you use the Core patterns, I recommend disabling them. To to disable Core patterns, you would use:
<?php
/**
* Remove core block patterns and disable remote block patterns.
*/
add_action(
'after_setup_theme',
function () {
remove_theme_support( 'core-block-patterns' );
},
15
);Code language: PHP (php)Not all themes support Core remote patterns, so use this on a case-by-case basis.
Theme remote patterns

Viewing a Pattern on the Pattern Directory
Remote patterns from themes are declared in the theme’s theme.json file:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"patterns": [
"three-columns-with-images-and-text",
"media-text-with-image-on-the-left"
]
}Code language: JSON / JSON with Comments (json)These slugs match what’s on the Pattern Directory and are loaded remotely. These are registered with source as: pattern-directory/theme.
To disable remote patterns coming from a theme, you would use:
<?php
/**
* Remove core block patterns and disable remote block patterns.
*/
add_action(
'after_setup_theme',
function () {
add_filter( 'should_load_remote_block_patterns', '__return_false' );
},
15
);Code language: PHP (php)
Disabling Remote patterns also disables Core remote patterns
The filter should_load_remote_block_patterns is all-inclusive when it comes to loading remote patterns. Unfortunately it’s not possible to hook in early and de-register remote patterns prior to them loading via the REST API.
Local patterns
Local patterns are stored in your database as a post type named wp_blocks. This list view is typically hidden in the admin, but you can access the patterns by going to: https://yourdomain.com/wp-admin/edit.php?post_type=wp_block
Default Patterns View for Local Patterns
To create a local pattern, you can either click on “Add Pattern” from this screen, or you can create a pattern directly from the block editor by opening the contextual menu for a block.
Create Pattern Screen from the Block Inserter
When you first create a pattern, you will be asked if you want a Synced or Unsynced pattern.
Add New Pattern Screen From the Block Editor
Choosing between a Synced and Unsynced pattern is necessary, and I’ll go over them in detail later in this article. In general, if you don’t need to change the pattern if it’s copied into the editor, it can be a “Synced” pattern. If you need to copy and edit the pattern later in multiple locations, then it should be an “Unsynced” pattern.
Synced vs Unsynced Pattern Flowchart
Since synced and unsynced patterns are stored in your database, they are more easily editable and transportable than registered patterns.
Registered patterns
WordPress Function register_block_pattern
Although all patterns are technically registered patterns, the patterns I mention come from explicitly registering patterns via the function register_block_pattern or a block theme using the patterns directory. These registered patterns can come from themes, plugins, or even some custom code that is running elsewhere.
Let’s go over in the next section how to register custom patterns.
Registering block patterns
Each developer’s workflow is different when developing distributed patterns. The simplest way to get a pattern’s code is to select it via the tree view and to copy it via the contextual menu.
Copy Pattern Code Via the Contextual Menu
Let’s take the quote code from earlier and turn it into a registered block pattern.
<!-- wp:quote -->
<blockquote class="wp-block-quote"><!-- wp:paragraph -->
<p>This is a quote.</p>
<!-- /wp:paragraph --><cite> - Me</cite></blockquote>
<!-- /wp:quote -->Code language: HTML, XML (xml)First, I need a name for the pattern. A good rule of thumb is to use a prefixed namespace followed by the pattern name. In this case, I’ll use the name dlxplugins/custom-quote.
I’ll then use the function register_block_pattern to register my pattern.
The format for register_block_pattern is as follows:
/**
* Registers a block pattern.
*
* @since 5.5.0
*
* @param string $pattern_name Block pattern name including namespace.
* @param array $pattern_properties {
* List of properties for the block pattern.
*
* @type string $title Required. A human-readable title for the pattern.
* @type string $content Optional. Block HTML markup for the pattern.
* If not provided, the content will be retrieved from the `filePath` if set.
* If both `content` and `filePath` are not set, the pattern will not be registered.
* @type string $description Optional. Visually hidden text used to describe the pattern
* in the inserter. A description is optional, but is strongly
* encouraged when the title does not fully describe what the
* pattern does. The description will help users discover the
* pattern while searching.
* @type int $viewportWidth Optional. The intended width of the pattern to allow for a scaled
* preview within the pattern inserter.
* @type bool $inserter Optional. Determines whether the pattern is visible in inserter.
* To hide a pattern so that it can only be inserted programmatically,
* set this to false. Default true.
* @type string[] $categories Optional. A list of registered pattern categories used to group
* block patterns. Block patterns can be shown on multiple categories.
* A category must be registered separately in order to be used here.
* @type string[] $keywords Optional. A list of aliases or keywords that help users discover
* the pattern while searching.
* @type string[] $blockTypes Optional. A list of block names including namespace that could use
* the block pattern in certain contexts (placeholder, transforms).
* The block pattern is available in the block editor inserter
* regardless of this list of block names.
* Certain blocks support further specificity besides the block name
* (e.g. for `core/template-part` you can specify areas
* like `core/template-part/header` or `core/template-part/footer`).
* @type string[] $postTypes Optional. An array of post types that the pattern is restricted
* to be used with. The pattern will only be available when editing one
* of the post types passed on the array. For all the other post types
* not part of the array the pattern is not available at all.
* @type string[] $templateTypes Optional. An array of template types where the pattern fits.
* @type string $filePath Optional. The full path to the file containing the block pattern content.
* }
* @return bool True if the pattern was registered with success and false otherwise.
*/
register_block_pattern( string $pattern_name, array $pattern_properties ): boolCode language: PHP (php)- Pattern Name (String, must be namespaced)
- Pattern Parameters (array)
- title – Pattern title.
- content – The JavaScript escaped content.
- description – A description for the pattern.
- categories (array) – List of categories the block pattern belongs to.
- keywords (array) – List of keywords to search for your pattern.
- viewportWidth (int) – Viewport width to preview the pattern at.
- blockTypes (array) – Namespace of blocks the pattern is compatible with.
- postTypes (array) – List of post types the pattern can be shown in.
- inserter (boolean ) – Whether the pattern is visible in the block inserter.
- templateTypes (array) – List of available templates the pattern can be used for.
- filePath (string) – Full path to the block pattern file.
For the quotes pattern registration, I can keep it simple and provide basic registration arguments.
<?php
/**
* Register quotes pattern.
*/
add_action(
'init',
function () {
register_block_pattern(
'dlxplugins/custom-quote',
array(
'title' => 'Custom Quote',
'description' => 'A pattern for custom quotes.',
'content' => '<!-- wp:quote -->
<blockquote class="wp-block-quote"><!-- wp:paragraph -->
<p>This is a quote.</p>
<!-- /wp:paragraph --><cite> - Me</cite></blockquote>
<!-- /wp:quote -->',
'viewportWidth' => 450,
'categories' => array( 'testimonials' ),
'keywords' => array( 'quote', 'custom' ),
)
);
}
);
Code language: PHP (php)The above code registers my pattern and allows me to search for it in the block inserter.
My Custom Quote Shows in the Block Inserter as a Pattern
Registering block pattern categories
You may have noticed that I was able to set some categories for my pattern. To register a custom block category, I would use function register_block_pattern_category. Here’s how I would add a testimonials category.
<?php
/**
* Register quotes pattern.
*/
add_action(
'init',
function () {
register_block_pattern_category(
'testimonials',
array(
'label' => 'Testimonials',
)
);
register_block_pattern(
'dlxplugins/custom-quote',
array(
'title' => 'Custom Quote',
'description' => 'A pattern for custom quotes.',
'content' => '<!-- wp:quote -->
<blockquote class="wp-block-quote"><!-- wp:paragraph -->
<p>This is a quote.</p>
<!-- /wp:paragraph --><cite> - Me</cite></blockquote>
<!-- /wp:quote -->',
'viewportWidth' => 450,
'categories' => array( 'testimonials' ),
'keywords' => array( 'quote', 'custom' ),
)
);
}
);Code language: PHP (php)Here is the format for register_block_pattern_category.
/**
* Registers a pattern category.
*
* @since 5.5.0
*
* @param string $category_name Pattern category name including namespace.
* @param array $category_properties {
* List of properties for the block pattern category.
*
* @type string $label Required. A human-readable label for the pattern category.
* }
* @return bool True if the pattern was registered with success and false otherwise.
*/Code language: PHP (php)
Make sure you register your block categories before your patterns.
You may get an unregistered category warning if you try to register a pattern for a category that doesn’t exist.
Registering a block theme pattern
If you have a block theme, any patterns with the patterns folder will be auto-registered. It has all the same properties as register_block_pattern, albeit the arguments are in the page’s header. Here’s an example from the Ollie theme for a registered theme pattern.
Path: /patterns/faq.php
<?php
/**
* Title: FAQ
* Slug: ollie/faq
* Description:
* Categories: ollie/features
* Keywords: faq, text, features
* Viewport Width: 1500
* Block Types:
* Post Types:
* Inserter: true
*/
?>
<!-- begin pattern -->Code language: PHP (php)You’ll still have to register your block pattern categories as mentioned earlier using register_block_pattern_category.
Creating local patterns using synced and unsynced patterns
As mentioned earlier, you can access your local patterns by navigating to: https://yourdomain.com/wp-admin/edit.php?post_type=wp_block
Block Patterns View in the wp_block Post Type
You’re able to add a local pattern from this screen by clicking “Add Pattern”, or you can do some from the block editor by selecting any block and clicking “Create Pattern.” This is demonstrated by the video below.
When creating the Pattern, you’ll be presented whether you want the pattern Synced or (unchecked) Unsynced. Let me explain what happens when a pattern is Synced vs Unsynced.
Synced vs Unsynced Pattern Flowchart
Creating Synced patterns
Synced Checkbox for Creating a New Pattern
A Synced pattern is a global pattern. It can only be changed in one place, and any edits of the pattern will filter down to all copies of the pattern. For example, you can create a synced pattern of a testimonials pattern. You can drop this in on as many pages as you’d like. Changing a testimonial will update the pattern throughout your site. Let’s observe this in practice.
Internally, the synced pattern is wrapped in a core/block block and is loaded via its pattern’s post ID. This is why it takes a bit to load in Synced patterns are they are loading in remotely in the block editor.
In the following screenshot, I’ll be creating a new pattern from a testimonials block.
Creating a New Pattern From an Existing Block
I’ll create a new “Synced” pattern from this pattern.
This Pattern is now saved locally in the database under the wp_block post type. In the block editor, you’ll see a purple border and icon, which is how you can tell it is synced.
Global Purple Border on Synced Patterns
Note the Purple Border
All synced patterns have a purple icon and border.
If you copy a Synced pattern, but want to change it without affecting the original, you can Detach it by selecting the pattern and opening the contextual menu.
Detach a Synced Pattern and Make it a Normal Pattern
You’ll also see an “Edit original” button on a Synced pattern.
Edit Original Button on a Synced Pattern
You’re able to edit the original, but it takes you to a new screen.
Editing the Original
Editing the original here edits all instances of this pattern.
A downside of Synced patterns is what if I want to keep the design, but change the testimonials from page to page? In this case, you’ll want to detach the pattern, or use an “Unsynced” pattern instead.
While there’s no way to change from a Synced to an Unsynced pattern after it’s been set, you can duplicate a Synced Pattern to create an Unsynced version.
Duplicate a Synced Pattern to Create an Unsynced Pattern
Synced patterns can be a life-saver, especially if you’re re-using common elements. However, if you need to change patterns from page to page, then Synced patterns will not work for you and you’re better off with Unsynced patterns.
Synced patterns are great for items that never change. If you need to change content from page to page, you need Unsynced patterns.
Creating Unsynced patterns
Unsynced patterns are best for patterns that need to change from page to page, such as some content or links here and there. In this example, I’ll create a pattern for a single testimonial. I’ll be doing this by unchecking the Synced pattern option.
Uncheck Synced to Create a Local Unsynced Pattern
I can then insert the pattern as I would any other normal block using the slash command.
Unsynced patterns are great for common design elements that can be copied and customized. However, you run into the rabbit hole of having to update each instance should a design change. For example, it is possible to find instances of a Synced pattern using a plugin like Find My Blocks, but not Unsynced patterns. As a result of this, it’s best to keep Unsynced patterns to items you can change the design globally of, but keep the content unique.
If working heavily with Unsynced patterns, it is advised to keep design out of the pattern as much as possible, relying on an existing design system and utilizing global style elements.
How to get your pattern library under control
An Overloaded Pattern Library With All Patterns Loaded
With local, registered, and remote patterns, the Patterns view in the Block Editor can quickly become overwhelming. Let me show you some tips on how to get your pattern library under control.
How to hide Core and Remote Patterns
This snippet will hide all Core and Remote patterns, instantly freeing up your library.
<?php
/**
* Remove core block patterns and disable remote block patterns.
*/
add_action(
'after_setup_theme',
function () {
remove_theme_support( 'core-block-patterns' );
add_filter( 'should_load_remote_block_patterns', '__return_false' );
},
15
);Code language: PHP (php)The result is a much more stream-lined Patterns view.
A Consolidated Patterns View With Remote and Core Patterns Disabled
How to show the Patterns post type view and the Patterns Category
To view local patterns, you can navigate to: https://yourdomain.com/wp-admin/edit.php?post_type=wp_block
Here’s how to enable it and the built-in categories taxonomy:
<?php
add_action(
'admin_menu',
function () {
add_menu_page(
__( 'Patterns', 'pattern-wrangler' ),
__( 'Patterns', 'pattern-wrangler' ),
'manage_options',
'edit.php?post_type=wp_block',
'',
'dashicons-layout',
6
);
add_submenu_page(
'edit.php?post_type=wp_block',
__( 'All Patterns', 'pattern-wrangler' ),
__( 'All Patterns', 'pattern-wrangler' ),
'edit_posts',
'edit.php?post_type=wp_block',
'',
1
);
add_submenu_page(
'edit.php?post_type=wp_block',
__( 'Categories', 'pattern-wrangler' ),
__( 'Categories', 'pattern-wrangler' ),
'edit_posts',
'edit-tags.php?taxonomy=wp_pattern_category&post_type=wp_block',
'',
5
);
},
15
);Code language: PHP (php)Here’s how it would show up in the admin:
All Patterns View in the Admin Panel
How to show the customizer
If you’re in Full-site Editing and you need access to the customizer, you can use this code snippet:
/**
* Re-enable the customizer UI.
*/
add_action(
'init',
function () {
add_action( 'customize_register', '__return_true' );
},
15
);Code language: PHP (php)How to hide theme patterns
If you want to hide all patterns coming from your theme, you can use this snippet:
/**
* De-register theme patterns.
*/
add_action(
'init',
function () {
// Get the active theme.
$theme = wp_get_theme();
// Let's get some theme data.
$paths_to_search = array(
$theme->stylesheet,
);
// Check if this is a child theme.
if ( $theme->parent() ) {
$parent_theme = wp_get_theme( $theme->parent()->template );
$paths_to_search[] = $parent_theme->template;
}
$paths_to_search = array_unique( $paths_to_search );
// Get all registered patterns.
$patterns = \WP_Block_Patterns_Registry::get_instance();
$all_patterns = $patterns->get_all_registered();
// Loop through all patterns and deregister any that are from the active or child theme.
foreach ( $all_patterns as $index => $pattern ) {
$file_path = $pattern['filePath'] ?? '';
if ( empty( $file_path ) ) {
continue;
}
// Check if the pattern is from the active or child theme.
foreach ( $paths_to_search as $path ) {
if ( false !== strpos( $file_path, 'themes/' . $path ) ) {
unregister_block_pattern( $pattern['name'] );
}
}
}
},
50
);Code language: PHP (php)How to hide patterns from plugins
Here’s how to hide all patterns from plugins, such as WooCommerce:
/**
* De-register all plugin patterns.
*/
add_action(
'init',
function () {
// Get all registered patterns.
$patterns = \WP_Block_Patterns_Registry::get_instance();
$all_patterns = $patterns->get_all_registered();
// Loop through all patterns and deregister any that are from active plugins.
foreach ( $all_patterns as $index => $pattern ) {
// Check the path for the `plugins` folder.
$file_path = $pattern['filePath'] ?? '';
if ( empty( $file_path ) ) {
continue;
}
// Deregister any with the plugin in their path.
if ( false !== strpos( $file_path, '/plugins' ) ) {
unregister_block_pattern( $pattern['name'] );
}
}
},
100
);Code language: PHP (php)Allow Patterns for export
Patterns by default can’t be exported. This small snippet will allow them to be exportable.
/**
* Make patterns post type exportable.
*/
add_filter(
'register_post_type_args',
function ( $args, $post_type ) {
if ( 'wp_block' === $post_type ) {
$args['can_export'] = true;
$args['_builtin'] = false;
}
return $args;
},
5,
2
);Code language: PHP (php)Use free plugin Pattern Wrangler for no-code manipulation
All of the above controls and snippets are part of the Pattern Wrangler plugin if you do not want to touch code.
Conclusion
Block patterns are powerful parts of the WordPress editor. By understanding how the Pattern Library is populated and how synced, unsynced, local, and registered patterns differ, you can gain full control over your pattern library.
For smaller sites, patterns can be a time-saver that reduces repetitive design work. For larger projects, they can become an architectural tool, helping enforce branding and streamlining workflows across teams. The key is knowing when to lean on synced patterns for global re-use, or unsynced patterns for copying and making quick changes.
If left unmanaged, patterns can overwhelm your editor with clutter. That’s why tools like Pattern Wrangler and complementary plugins such as Find My Blocks exist: they give you visibility, guardrails, and migration paths so patterns remain an asset
As WordPress continues to evolve, patterns will only become more central to theme design, content workflows, and site building at scale. For further reading, consider reading even more about block patterns.
Like the tutorial you just read? There's more like it.
There's more where that came from. Enter your email and I'll send you more like it.




























