How to Disable Specific Gutenberg Blocks in WordPress
WordPress out of the box provides a huge set of blocks, some of which you may simply not need on your site. To prevent them from interfering when creating and editing posts, specific blocks can be disabled.
Blocks can be deactivated in various ways using PHP, JavaScript, or through user settings. The choice depends on the specific task. For example, using JavaScript to limit blocks can be convenient if you are already using it for other tasks. On the other hand, PHP offers a server-side solution that can be easily added to existing plugins and themes.
Below, we will explore all possible options to remove specific blocks from the Gutenberg block editor.
Disabling Blocks for the Current User (Settings)
You can hide specific blocks using the editor's settings panel.
To do this in the editor or site editor:
- Click on the options menu in the top right corner of the screen (three vertical dots).
- Select "Settings".
- In the pop-up window, go to the "Blocks" section.
- Check those you want to hide (from the list of registered blocks).
These settings are saved for the user, meaning the blocks are not deleted, but simply hidden for your user while remaining available to other users.
Disabling Blocks via PHP
For this, we will use the hook allowed_block_types_all. The hook's callback accepts two parameters:
$allowed_block_types
– An array of block type slugs or a boolean value to enable or disable all blocks.$block_editor_context
– The current context of the block editor.
It is important to note that when using this hook, any block patterns composed of disabled blocks will also become unavailable to the user.
Important! For a block to be disabled via PHP, it must also be registered through PHP (and not through JS). Therefore, it is recommended to register blocks through the block.json file or the register_block_type() function.
Whitelist (Allowed Blocks)
A simple example that allows users to insert only the Heading, List, Image, and Paragraph blocks. This can be considered a "whitelist of allowed blocks".
To test the following code, add it to the functions.php file of the theme or include it in a plugin.
// Remove all blocks except the specified ones add_filter( 'allowed_block_types_all', 'example_allowed_block_types', 10, 2 ); /** * @param array|bool $allowed_block_types Array of block type slugs, or boolean to enable/disable all. * @param object $block_editor_context The current block editor context. * * @return array The array of allowed block types. */ function example_allowed_block_types( $allowed_block_types, $block_editor_context ) { $allowed_block_types = array( 'core/heading', // Heading block 'core/image', // Image block 'core/list', // List block 'core/paragraph', // Paragraph block ); return $allowed_block_types; }
Using Conditions
Let's make this example a bit more realistic.
When it is necessary to restrict authors' access to only certain blocks, but provide editors and administrators access to all. For this, you can use the current_user_can() function:
// Remove all blocks except the specified ones add_filter( 'allowed_block_types_all', 'example_allowed_block_types', 10, 2 ); /** * @param array|bool $allowed_block_types Array of block type slugs, or boolean to enable/disable all. * @param object $block_editor_context The current block editor context. * * @return array The array of allowed block types. */ function example_allowed_block_types( $allowed_block_types, $block_editor_context ) { // If the current user does not have the required permissions, limit the blocks. if ( ! current_user_can( 'publish_pages' ) ) { $allowed_block_types = array( 'core/heading', // Heading block 'core/image', // Image block 'core/list', // List block 'core/paragraph', // Paragraph block ); return $allowed_block_types; } // allow all blocks return true; }
For a complete list of roles and capabilities see here.
Using the $block_editor_context Parameter
The $block_editor_context parameter expands the possibilities of conditions under which blocks need to be disabled. For example, you can get the type of the editable post, find out whether the user is working in the editor or in the site editor, etc.
Let's modify the code to limit blocks only when a post is being edited and allow all blocks when the site is being edited. That is, we will leave a specific list of blocks only for posts of type post.
This approach can be useful if your site uses custom post types intended for placing only certain types of content.
// Remove all blocks except the specified ones add_filter( 'allowed_block_types_all', 'example_allowed_block_types', 10, 2 ); /** * @param array|bool $allowed_block_types Array of block type slugs, or boolean to enable/disable all. * @param object $block_editor_context The current block editor context. * * @return array The array of allowed block types. */ function example_allowed_block_types( $allowed_block_types, $block_editor_context ) { // Applies only in the editor when editing posts. if ( 'core/edit-post' === $block_editor_context->name && 'post' === ( $block_editor_context->post->post_type ?? '' ) ) { $allowed_block_types = array( 'core/heading', // Heading block 'core/image', // Image block 'core/list', // List block 'core/paragraph', // Paragraph block ); return $allowed_block_types; } // allow all blocks return true; }
$block_editor_context->name
can contain:
core/edit-post
– Editorcore/edit-site
– Site editorcore/widgets
– Widget editorcore/customize-widgets
– Widget editor in the custom interface
Blacklist (Disallowed Blocks)
Above we allowed blocks. But if you have hundreds of blocks, it is more convenient to specify only those that need to be banned.
To achieve this, we can specify the unnecessary blocks in an array, then programmatically obtain the entire list of existing blocks and exclude the specified ones.
To get the entire list of blocks, we use the method WP_Block_Type_Registery::get_all_registered().
Let’s consider an example of disabling the Navigation and Query blocks for users who do not have permission for edit_theme_options
(usually this is an administrator privilege).
add_filter( 'allowed_block_types_all', 'wpkama_disable_gutenberg_blocks', 30, 2 ); function wpkama_disable_gutenberg_blocks( $allowed_blocks, $block_editor_context ) { $disable_blocks = [ 'core/calendar', 'core/comment-author-name', 'core/comment-content', 'core/comment-date', 'core/comment-edit-link', 'core/comment-reply-link', 'core/comment-template', 'core/comments', 'core/comments-pagination', 'core/comments-pagination-next', 'core/comments-pagination-numbers', 'core/comments-pagination-previous', 'core/comments-title', 'core/embed', ]; // Get all registered blocks if $allowed_block_types is not already set. if( ! is_array( $allowed_blocks ) || empty( $allowed_blocks ) ){ $registered_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered(); $allowed_blocks = array_keys( $registered_blocks ); } foreach( $allowed_blocks as $index => $block_id ){ if( in_array( $block_id, $disable_blocks, true ) ){ unset( $allowed_blocks[ $index ] ); } } return array_values( $allowed_blocks ); // note: array list required }
Disabling Blocks via JavaScript
Implementing block restrictions using JavaScript requires creating and enqueueing a JavaScript file in the editor.
For the example below, the script code will be located in a theme file (the path to the script file will be specified relative to the theme).
-
Create a file
restrict-blocks.js
(the name is arbitrary) and place it in theassets/js
folder of the theme. - Enqueue this file using the enqueue_block_editor_assets hook and the standard wp_enqueue_script() function.
add_action( 'enqueue_block_editor_assets', 'example_enqueue_block_restrictions' ); function example_enqueue_block_restrictions() { wp_enqueue_script( 'example-enqueue-block-variations', get_template_directory_uri() . '/assets/js/restrict-blocks.js', array( 'wp-blocks', 'wp-dom-ready' ), wp_get_theme()->get( 'Version' ), false ); }
Note that the dependencies wp-blocks
and wp-dom-ready
are needed for restrictions in the examples below.
Whitelist (Allowed Blocks)
Here, the logic differs from the PHP option above.
To keep only a few blocks, you first need to get a list of all existing blocks using the wp.blocks.getBlockTypes()
function. Then iterate through the list and disable all blocks that are not specified in the whitelist.
Blocks are unregistered using the method wp.blocks.unregisterBlockType()
, which takes the block name. This method comes with the dependency wp-blocks
(mentioned when registering the script).
wp.domReady( () => { // Allow only the Heading, Image, List, and Paragraph blocks. const allowedBlocks = [ 'core/heading', 'core/image', 'core/list', 'core/paragraph', ]; wp.blocks.getBlockTypes().forEach( blockType => { if ( allowedBlocks.indexOf( blockType.name ) === -1 ) { wp.blocks.unregisterBlockType( blockType.name ); } } ); } );
It is essential to use wp.domReady
when unregistering blocks. Otherwise, the function may trigger too early and not remove the block.
Using Conditions
Just like in PHP methods, conditions can be added. For example, the method canUser() from the package @wordpress/data-core allows you to get permissions, and the package @wordpress/data-core-editor provides a convenient method getCurrentPostType().
These methods allow you to determine the current post type and check if the user can update settings.
wp.domReady( () => { const { canUser } = wp.data.select( 'core' ); const { getCurrentPostType } = wp.data.select( 'core/editor' ); // Check user permissions and get the current post type. const canUserUpdateSettings = canUser( 'update', 'settings' ); const currentPostType = getCurrentPostType(); const allowedBlocks = [ 'core/heading', 'core/image', 'core/list', 'core/paragraph', ]; if ( ! canUserUpdateSettings && currentPostType === 'post' ) { wp.blocks.getBlockTypes().forEach( blockType => { if ( allowedBlocks.indexOf( blockType.name ) === -1 ) { wp.blocks.unregisterBlockType( blockType.name ); } } ); } } );
Blacklist (Prohibited Blocks)
When you need to disable only a few blocks, it's more convenient to use the following code. For example, if we need to remove two blocks core/navigation
and core/query
, in this case, there's no need to get a list of all blocks; you can simply disable the unnecessary blocks:
wp.domReady( () => { wp.blocks.unregisterBlockType( 'core/navigation' ); wp.blocks.unregisterBlockType( 'core/query' ); } );
If conditions are needed, just like in the previous example, use the methods from the packages core
and core/editor
:
wp.domReady( () => { const { canUser } = wp.data.select( 'core' ); const { getCurrentPostType } = wp.data.select( 'core/editor' ); if ( ! canUser( 'update', 'settings' ) && getCurrentPostType() === 'post' ) { wp.blocks.unregisterBlockType( 'core/navigation' ); wp.blocks.unregisterBlockType( 'core/query' ); } } );
The JavaScript option is probably more preferable because, ultimately, the registration of blocks is done in JavaScript, and therefore, in this case, we have more possibilities. For example, if we registered a block through JS, that block simply won't be visible in PHP, whereas in JS it will exist.
Disabling Block Variations
Often block variations can be mistaken for separate blocks, but this is not the case.
In simple terms, block variations are one block that has different options, and each of these options appears in the editor as a separate block.
For example, embeds:
All these blocks are one block core/embed
, and if we disable this block using the examples above, we will disable all variations of this block. Therefore, they cannot be disabled using the previously described methods. However, sometimes it's necessary to disable a specific variation while leaving the other variations.
Another example of a variation is groups (group):
Let's consider an example of disabling the group variations Row
, Stack
and the embed variation YouTube
.
wp.domReady( () => { wp.blocks.unregisterBlockVariation( 'core/group', 'group-row' ); wp.blocks.unregisterBlockVariation( 'core/group', 'group-stack' ); wp.blocks.unregisterBlockVariation( 'core/embed', 'youtube' ); } );
For more information about block variations, refer to the article "An Introduction to Block Variations".
Attribute allowedBlocks: Whitelist of Blocks Inside Blocks
Some blocks can contain other blocks. Let's call such blocks container blocks. An example of such a container block is the "Group" block. Sometimes it may be necessary to limit the list of blocks that can be used inside a container block.
For WordPress 6.4, the allowedBlocks
attribute supports four blocks:
- Column
- Cover
- Media & Text
- Group - includes variations:
- Row
- Stack
- Grid
For these blocks, you can use the allowedBlocks
attribute to specify a list of permitted blocks inside the container block. Blocks not included in this list will be unavailable for insertion inside the container block.
For example, if you want to allow only the "Heading" and "Paragraph" blocks inside a specific container block, you should use the following block setting:
{"allowedBlocks":["core/heading","core/paragraph"]}
Let's look at another block locking parameter block locking that has a visual interface:
However, there is no user interface for the allowedBlocks
attribute. Therefore, to illustrate how the allowedBlocks
attribute works, let's consider the "call-to-action" pattern template (with an image on the right) in the Twenty Twenty-Four theme.
The template is structured as follows: it consists of a "Group" block serving as a wrapper that contains a "Columns" block, divided into two separate "Column" blocks. Our task is to restrict the blocks that can be added to each column.
Let's make it so that only the following blocks can be added to the left column: Buttons, Heading, List, and Paragraph. And only the "Image" block can be added to the right.
Here’s a simplified version of the template, focused on the markup of the Columns block with applied attributes.
<!-- wp:column {"allowedBlocks":["core/buttons","core/heading","core/list","core/paragraph"],"verticalAlignment":"center","width":"50%"} --> <div class="wp-block-column is-vertically-aligned-center" style="flex-basis:50%">[...] </div> <!-- /wp:column --> <!-- wp:column {"allowedBlocks":["core/image"],"verticalAlignment":"center","width":"50%"} --> <div class="wp-block-column is-vertically-aligned-center" style="flex-basis:50%">[...] </div> <!-- /wp:column -->
The allowed blocks in each Columns block are now restricted. Thus, if you use this pattern in content, the blocks that can be inserted into the columns will be limited. This approach can be useful in projects where consistency and prescribed content structure are important.
It is important to note that since this block restriction is controlled by an attribute, users can theoretically switch to the Code Editor, remove the attribute, and then add any blocks they need. If this possibility also needs to be removed, you can restrict access to the Code Editor using PHP.
Disabling Access to the Code Editor
The Code Editor allows viewing the basic markup of the block for a page or post. This can be useful, but only if you are an experienced user; otherwise, you might accidentally break the block markup by editing the content. To restrict users' access to editing HTML code, add the following code to your functions.php file.
add_filter( 'block_editor_settings_all', 'example_restrict_code_editor_access', 10, 2 ); function example_restrict_code_editor_access( $settings, $context ) { $settings[ 'codeEditingEnabled' ] = false; return $settings; }
This code prevents access to the code editor for all users.
--
Source: https://developer.wordpress.org/news/2024/01/29/how-to-disable-specific-blocks-in-wordpress/