How to lock blocks and templates

Level: ,

In this short lesson, I explain briefly what block locking is and when it is useful for full site editing and describe techniques for locking blocks and templates.

Estimated reading time: 5 minutes

Updated April 20, 2022, for Gutenberg version 13.0.

What is block locking?

The primary use for block locking is to prevent the accidental removal of important blocks or to prevent specific users from removing blocks.

You can lock all WordPress core blocks and the experimental Gutenberg blocks. Block locking has two levels:

  • Can not remove
  • Can not move, which means that users can not move the block using drag or drop, the arrow keys, or the list view.

You can also use locking to restrict the editing of reusable blocks.

Locking a parent or container block (like a group) does not lock the inner blocks.
At this time, you need to lock blocks individually. There is a proposal to make it easier to lock all inner blocks, but the development of this feature is not complete yet.
It is also not possible to lock blocks using theme.json.

Locking blocks in the editor

Select the block you want to lock. Open the Options modal from the ellipsis menu in the block toolbar, and select the Lock menu item:

Select between lock all, disable movement, or prevent removal:

A locked block has a lock icon in the toolbar:

Locking blocks with code

You can also lock blocks with code in your block patterns, template parts, and templates.
The attribute you need to add to the block comment is called lock and the values for remove and move can be either true or false:

<!-- wp:heading {"lock":{"move":true,"remove":true}} -->
<h2>Heading two<br></h2>
<!-- /wp:heading -->

What is template locking?

With template locking, you can do two things: Lock a template or lock individual blocks inside a template.
This can be very useful, but there is a caveat: Template locking is more limited than locking blocks in the sense that it only works for custom post types.
You have to add the template lock during the post type registration or filter the post type object of an existing post type.

Template locking has two levels:

  • all: Can not add blocks or block patterns and can not move blocks.
  • insert: Can not add blocks or block patterns but can move blocks.

Users can still unlock and edit the default blocks you have added to the template if they have the correct user role privileges. They can also do things like saving, publishing, changing the title, adding taxonomies and featured images, etc.
In other words, it is not possible to create a new HTML file as a page template for your theme and then lock it with one setting: To do that, you would need to lock all blocks individually.

Locking blocks inside templates have the same options as regular block locking: move and remove.

Code example from the official documentation:

function myplugin_register_book_post_type() {
    $args = array(
        'public' => true,
        'label'  => 'Books',
        'show_in_rest' => true,
        'template' => array(
            array( 'core/image', array(
                'align' => 'left',
            ) ),
            array( 'core/heading', array(
                'placeholder' => 'Add Author...',
            ) ),
            array( 'core/paragraph', array(
                'placeholder' => 'Add Description...',
                'lock' => array(
                    'move'   => true,
                    'remove' => true,
                 ),
            ) ),
        ),

        template_lock => 'insert';
    );
    register_post_type( 'book', $args );
}
add_action( 'init', 'myplugin_register_book_post_type' );

Filtering the post type object of an existing post type:

function myplugin_register_template() {
    $post_type_object = get_post_type_object( 'blocks' );
    $post_type_object->template = array(
        array( 'core/paragraph', array(
            'placeholder' => 'Add Description...',
        ) ),
    );
    $post_type_object->template_lock = 'all';
}
add_action( 'init', 'myplugin_register_template' );

How to prevent users from unlocking blocks

To specify which user, user role, or capability should be able to lock and unlock blocks, you need to use the block_editor_settings_all filter. You can add this filter to your themes functions.php file.

The setting that you will be filtering is called canLockBlocks and accepts a true or false value:
True means that the user can lock and unlock blocks, false means that they can not lock or unlock. The default is true.

I have copied and edited the following example from the pull request by George Mamadashvili:

add_filter(
	'block_editor_settings_all',
	static function( $settings, $context ) {
		// Allow for the Editor role and above.
		$settings['canLockBlocks'] = current_user_can( 'delete_others_posts' );

		// Only enable for specific user(s).
		$user = wp_get_current_user();
		if ( in_array( $user->user_email, array( 'user@example.com' ), true ) ) {
			$settings['canLockBlocks'] = false;
		}

		// Disable for posts/pages.
		if ( $context->post && $context->post->post_type === 'page' ) {
			$settings['canLockBlocks'] = false;
		}

		return $settings;
	},
	10,
	2
);

Resources

Locking blocks in WordPress 5.9

Creating templates for custom post types