WordPress.org

WordPress Developer Blog

15 ways to curate the WordPress editing experience

15 ways to curate the WordPress editing experience

Customizing the WordPress Editor can greatly enhance the user experience by tailoring the interface to meet specific needs. By curating the editing environment, you can streamline content creation, reduce clutter, enforce consistency, and ensure that the tools available are relevant. 

This post will introduce you to 15 ways to curate the Editor and showcase the various methods currently available in WordPress.

Applying curation methods

Before diving into the examples, it’s important to understand that Editor curation can take many forms and be implemented in various ways. While many methods can be achieved with either theme.json, PHP, or JavaScript, some require a specific approach.

If you’d like to follow along, this guide assumes you want to add Editor modifications to a theme, but you can easily adapt them for use in a plugin. The main difference is where you place each filter or function.

Unless otherwise noted, if an example requires PHP code, place it in the theme’s functions.php file. If JavaScript is required, create a file named editor-curation-examples.js and place it in the theme’s assets/js folder.

Next, enqueue editor-curation-examples.js using the enqueue_block_editor_assets hook and the wp_enqueue_script() function. Insert this code in your theme’s functions.php file.

function example_enqueue_editor_curation_examples() {
	wp_enqueue_script(
		'example-enqueue-block-variations',
		get_template_directory_uri() . '/assets/js/editor-curation-examples.js',
		array( 'wp-blocks', 'wp-dom-ready' ),
		wp_get_theme()->get( 'Version' ),
		true // Print scripts in the footer. This is required for scripts to work correctly in the Site Editor.
	);
}
add_action( 'enqueue_block_editor_assets', 'example_enqueue_editor_curation_examples' );

Curation examples

The following examples just scratch the surface of what’s possible with the current curation methods available in WordPress. As you look through each one, consider how you could adapt it to your needs. 

Configure theme.json settings

When curating the editing experience in WordPress, the best place to start is with the settings property in your theme’s theme.json file. This file allows you to configure global and block-level settings that define the default behavior of the Editor. It’s also the easiest method to implement, so you should explore all possibilities within theme.json before considering PHP or JavaScript alternatives.

While there are many configurations available, here is a simple example that disables color support for the Heading block.

{
    "version": 3,
    "settings": {
        "blocks": {
            "core/heading": {
                "color": {
                    "text": false,
                    "background": false,
                    "link": false
                }
            }
        }
    }
}

Once applied, the Color panel will no longer appear in the block inspector.

Refer to the article Curating the Editor Experience documentation for additional theme.json examples.  

Disable specific blocks

Limiting the available blocks in the Editor is one of the best ways to simplify your users’ editing experience. While you can restrict blocks in both PHP and JavaScript, the simplest approach is with the powerful allowed_block_types_all filter. 

Here’s an example that limits the available blocks when the user is editing a post in the Post Editor.

/**
 * Filters the list of allowed block types based on the editing context.
 *
 * This function restricts the available block types to Heading, List, Image, and 
 * Paragraph when the user is editing posts in the Editor. When editing other post types
 * or in the Site Editor, all blocks are allowed.
 *
 * @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, including the editor type and the post being edited.
 *
 * @return array|bool The array of allowed block types when editing posts, or true to allow all blocks in other contexts.
 */
function example_allowed_block_types_when_editing_posts( $allowed_block_types, $block_editor_context ) {

	// Only apply in the Editor when editing posts.
	if ( 
		'core/edit-post' === $block_editor_context->name &&
		isset( $block_editor_context->post ) && 
		'post' === $block_editor_context->post->post_type
	) {
		$allowed_block_types = array(
			'core/heading',
			'core/image',
			'core/list',
			'core/list-item',
			'core/paragraph',
			'core/missing', // Displayed when a block type is no longer registered.
		);

		return $allowed_block_types;
	}

	// Allow all blocks in the Site Editor or when editing other post types.
	return true;
}
add_filter( 'allowed_block_types_all', 'example_allowed_block_types_when_editing_posts', 10, 2 );

When the code is applied, the block inserter will look like this: 

Refer to the article How to disable specific blocks in WordPress to learn more techniques and use cases for disabling blocks.

Unregister block variations

Block variations are often mistaken for blocks themselves. Consider the Row and Stack variations for the Group block or the many Embed block variations. Since these are not actual blocks, you need to use the unregisterBlockVariation function in JavaScript to remove them from the Editor. Unfortunately, there is no PHP alternative as of WordPress 6.6.

Here’s an example that disables many Embed block variations. When using unregisterBlockVariation, you must provide the original block name and the variation name you want to remove.

/**
 * Unregister selected Embed block variations.
 */
wp.domReady( () => {
    const embedVariations = [
        'animoto',
        'dailymotion',
        'hulu',
        'reddit',
        'tumblr',
        'vine',
        'amazon-kindle',
        'cloudup',
        'crowdsignal',
        'speaker',
        'scribd'
    ];

    embedVariations.forEach( ( variation ) => {
        wp.blocks.unregisterBlockVariation( 'core/embed', variation );
    } );
} );

Add this code to the editor-curation-example.js file, and the unregistered variations will no longer appear in the block inserter.

When unregistering variations on core WordPress blocks, wp.domReady is required. The function fires too early without it, and the variation is never removed. While wp.domReady might not be required to unregister some third-party block variations, it’s a good idea to use it consistently.

For more information on block variations, refer to the article An introduction to block variations.

Unregister block styles

WordPress provides several default block styles, such as the Rounded option for Image blocks. Disabling certain styles is a common curation technique, whether you’re providing your own block styles instead or want to simplify the interface.

You can unregister block styles in both PHP and JavaScript, but there is an important nuance. The PHP method only works for styles registered server-side with register_block_style. To disable styles registered with client-side code, which includes those provided by WordPress, you must use JavaScript with unregisterBlockStyle.

The following code disables the Image block’s Default and Rounded block styles.

/**
 * Unregister Image block styles.
 */
wp.domReady( function() {
    wp.blocks.unregisterBlockStyle( 'core/image', [ 'default', 'rounded' ] );
} );

Once the modification is applied to the editor-curation-example.js file, the inspector panel will look like this.

Disable block supports

Sometimes, the WordPress Editor might offer too many block-level styling options. While you can disable block supports in theme.json, you can also use the register_block_type_args, block_type_metadata_settings, and block_type_metadata PHP filters. JavaScript methods are available as well for more advanced customization.

These tools let you adjust block arguments based on different needs, such as the post type or the user’s permissions, which is not possible in theme.json. For example, you might want to disable custom color options for specific blocks when editing posts but not pages. This keeps the editing experience simple and relevant, ensuring users see only the tools they need.

For this example, let’s focus on the register_block_type_args filter which is applied to a block’s arguments array ($args) right before the block type is actually registered. The callback function for this filter accepts two parameters:

  • $args: Array of arguments for registering a block type.
  • $block_type: Block type name including namespace.

When a user edits posts, the following code will disable the color controls for Paragraph, Heading, List, and List Item blocks.

/**
 * Disable color controls for specific blocks when editing posts.
 *
 * @param array  $args       The original block type arguments.
 * @param string $block_type The name of the block type being registered.
 * @return array             Modified block type arguments.
 */
function example_disable_color_for_specific_blocks_on_posts( $args, $block_type ) {
    // Get the current post type using a utility function.
    $post_type = example_get_post_type();

    // Check if we are editing a post.
    if ( 'post' === $post_type ) {
        // List of block types to modify.
        $block_types_to_modify = [
            'core/paragraph',
            'core/heading',
            'core/list',
            'core/list-item'
        ];

        // Check if the current block type is in the list.
        if ( in_array( $block_type, $block_types_to_modify, true ) ) {
            // Disable color controls.
            $args['supports']['color'] = array(
                'text'       => false,
                'background' => false,
                'link'       => false,
            );
        }
    }

    return $args;
}
add_filter( 'register_block_type_args', 'example_disable_color_for_specific_blocks_on_posts', 10, 2 );

/**
 * Retrieve the current post type from query parameters.
 *
 * @return string The post type if found, otherwise an empty string.
 */
function example_get_post_type() {
	$post_type = '';

	if ( isset( $_GET['post'] ) ) {
		$post_type = get_post_type( absint( $_GET['post'] ) );
	} elseif ( isset( $_GET['post_type'] ) ) {
		$post_type = sanitize_key( $_GET['post_type'] );
	} elseif ( isset( $_GET['postType'] ) ) {
		$post_type = sanitize_key( $_GET['postType'] );
	}

	return $post_type;
}

Notice that a utility function is used to get the current post type. This is necessary because when the register_block_type_args filter runs, functions like get_current_screen() are unavailable.

Here’s a look at the inspector panel for a Heading block when this code is applied.

Enable block supports

In the previous example, block supports were removed from specific blocks. You can also add support using the register_block_type_args filter. However, if a block currently lacks a specific feature, there might be a good reason for it, such as an unresolved bug or it’s planned for a future release. Use this functionality with caution.

Here’s an example that adds duotone support to the image inside the Media & Text block.

/**
 * Enable duotone for Media & Text blocks.
 *
 * @param array  $args       The block type args.
 * @param string $block_type The block type.
 * @return array             The modified block type args.
 */
function example_enable_duotone_to_media_text_blocks( $args, $block_type ) {
	
	// Only apply the filter to Media & Text blocks.
	if ( 'core/media-text' !== $block_type ) {
		return $args;
	}

	$args['supports'] ??= [];
	$args['supports']['filter'] ??= [];
	$args['supports']['filter']['duotone'] = true;

	$args['selectors'] ??= [];
	$args['selectors']['filter'] ??= [];
	$args['selectors']['filter']['duotone'] = '.wp-block-media-text .wp-block-media-text__media';

	return $args;
}
add_filter( 'register_block_type_args', 'example_enable_duotone_to_media_text_blocks', 10, 2 );

If you look closely at the screenshot below, you’ll notice that the drag handle on the image also has a duotone filter applied. Despite this minor bug, adding a duotone effect to the Media & Text block works as expected. Just make sure to test your modifications thoroughly.

Disable the user interface for locking blocks

The Block Locking API is an excellent curation tool that allows you to restrict the movement and removal of specific blocks. By default, users can unlock locked blocks, which might not be desirable.

The Editor includes settings that can be modified by the block_editor_settings_all filter. The callback function for this filter accepts two parameters:

  • $settings: The array of current Editor settings.
  • $context: The current block editor context.

One of the settings in the Editor is canLockBlocks. The following example checks if the current user is an Administrator (or has similar permissions). If not, the block locking interface is disabled.

/**
 * Allow only Administrators to access the block locking user interface.
 * 
 * @param array                   $settings Default editor settings.
 * @param WP_Block_Editor_Context $context  The current block editor context.
 */
function example_restrict_block_locking_to_administrators( $settings, $context ) {
	$is_administrator = current_user_can( 'edit_theme_options' );

	if ( ! $is_administrator ) {
		$settings[ 'canLockBlocks' ] = false;
	}

	return $settings;
}
add_filter( 'block_editor_settings_all', 'example_restrict_block_locking_to_administrators', 10, 2 );

After this code is added to your theme’s functions.php file, non-Administrators can no longer lock or unlock blocks.

There are many Editor settings, too many to cover in this article. To see all available settings, open the Editor and enter the following command in your browser’s console:


wp.data.select( 'core/editor' ).getEditorSettings();

This will display all the available settings and their current values. Each can be modified using the block_editor_settings_all filter.

Disable the Code Editor

Building on the previous example, to ensure users cannot tamper with locked blocks, you need to disable the Code Editor. Without this step, users could manually remove the locking attributes, even if they can no longer access the block locking interface.

To do so, set the codeEditingEnabled setting to false. Here’s the updated code snippet.

/**
 * Restrict access to the block locking UI and the Code editor to Administrators.
 * 
 * @param array                   $settings Default editor settings.
 * @param WP_Block_Editor_Context $context  The current block editor context.
 */
function example_restrict_block_locking_and_code_editor_to_administrators( $settings, $context ) {
	$is_administrator = current_user_can( 'edit_theme_options' );

	if ( ! $is_administrator ) {
		$settings[ 'canLockBlocks' ]      = false;
		$settings[ 'codeEditingEnabled' ] = false;
	}

	return $settings;
}
add_filter( 'block_editor_settings_all', 'example_restrict_block_locking_and_code_editor_to_administrators', 10, 2 );

Once applied, users can still see the Code editor menu item, but it will be disabled.

Disable inspector tabs

Inspector tabs were introduced in WordPress 6.2 to help organize the inspector by separating a block’s settings and styles. While this is useful in most cases, there may be situations where you want to disable this functionality for workflow reasons or other considerations.

You can control which blocks have inspector tabs using the blockInspectorTabs Editor setting. This setting accepts an array of block styles. You can also disable tabs for all blocks by setting the default option to false.

The following example disables tabs for the Button block.

/**
 * This function modifies the block editor settings to disable inspector tabs
 * for the 'core/button' block.
 *
 * @param array $settings The current block editor settings.
 * @return array          The modified block editor settings.
 */
function example_disable_inspector_tabs_for_specific_blocks( $settings ) {
	if ( ! isset( $settings['blockInspectorTabs'] ) ) {
		$settings['blockInspectorTabs'] = array();
	}

	$settings['blockInspectorTabs'] = array_merge(
		$settings[ 'blockInspectorTabs' ],
		array( 
			'default'     => true, // Set to false to disable tabs for all blocks.
			'core/button' => false,
		),
	);

	return $settings;
}
add_filter( 'block_editor_settings_all', 'example_disable_inspector_tabs_for_specific_blocks' );

Here’s the before and after view for the Button block.

Disable Openverse

Starting with WordPress 6.2, Openverse images are integrated into the Media panel in the inspector for easy insertion. If you prefer to disable this functionality, you can turn it off using the block_editor_settings_all filter since enableOpenverseMediaCategory is another Editor setting.

/**
 * Disable Openverse.
 *
 * @param array $settings The current block editor settings.
 * @param array $context  The current editor context, including post information.
 * @return array          The modified block editor settings.
 */
function example_disable_openverse( $settings, $context ) {
	$settings['enableOpenverseMediaCategory'] = false;
	return $settings;
}
add_filter( 'block_editor_settings_all', 'example_disable_openverse', 10, 2 );

The result will look like this:

Set the default image size

When a user inserts an image into the Editor, it will default to the large size unless you have made other modifications to your site. Using the block_editor_settings_all filter, you can easily define the default size.

Here’s an example that sets the size to full and uses the $context to restrict this modification to posts. Pages and other custom post types will retain the large default.

/**
 * Set the default image size when inserted into the Editor.
 *
 * @param array $settings The current block editor settings.
 * @param array $context  The current editor context, including post information.
 * @return array          The modified block editor settings.
 */
function example_set_default_image_size( $settings, $context ) {
	if ( 
		! empty( $context->post ) && 
		'post' === $context->post->post_type 
	) {
		// Set the default image size to full.
		$settings['imageDefaultSize'] = 'full';
	}

	return $settings;
}
add_filter( 'block_editor_settings_all', 'example_set_default_image_size', 10, 2 );

Disable the Block Directory

Third-party blocks from the Block Directory appear in the block inspector under the Blocks panel when you perform a search. This functionality allows you to insert a block and install the associated plugin directly from the Editor. You can disable this in PHP using the following line of code:

/**
 * Globally disable the Block Directory.
 */
remove_action( 'enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets' );

The Block Directory can also be disabled with a few lines of JavaScript.

/**
 * Globally disable the Block Directory.
 */
wp.domReady( function() {
	wp.plugins.unregisterPlugin( 'block-directory' );
} );

Either way, the result will look like this: 

Disable the Pattern Directory

By default, the Pattern panel in the inspector includes a curated list of block patterns from the Pattern Directory. You can disable these patterns in PHP using the following line of code:

/**
 * Globally disable the Pattern Directory.
 */
add_filter( 'should_load_remote_block_patterns', '__return_false' );

Once applied, you will only see patterns provided by the current theme or created by users. The Twenty Twenty-Four theme was used in the screenshots below.

Disable access to the Template Editor

The Template Editor allows you to modify, swap, or create templates directly from the Post Editor. While useful, you might want to disable this feature for your users.

The following code uses get_current_screen() to conditionally disable the Template Editor when editing posts. It remains available for pages and other custom post types. You can also add user capability checks if needed.

/**
 * Disable the Template Editor for Posts.
 */
function example_disable_template_editor_for_posts() {
    $screen = get_current_screen();

    // Check if we are editing the 'post' post type.
    if ( 'post' === $screen->post_type ) {
        remove_theme_support( 'block-templates' );
    }
}
add_action( 'current_screen', 'example_disable_template_editor_for_posts' );

The result will look like this:

Unregister formatting options on RichText blocks

Blocks that are powered by the RichText component, such as Paragraph and Heading blocks, include a variety of formatting options by default, which you may not want users to have access to.

Here’s an example that disables the Inline code, Inline image, Keyboard input, Language, and Strikethrough options.

/**
 * Globally disable RichText formatting options.
 */
wp.domReady( function() {
    const formatsToUnregister = [
        'core/code'
        'core/image',
        'core/keyboard',
        'core/language',
        'core/strikethrough',
    ];

    formatsToUnregister.forEach( function( format ) {
        wp.richText.unregisterFormatType( format );
    } );
} );

Enqueue this JavaScipt much like you would when disabling block styles and variations. Then, if you toggle the More menu on a Paragraph block, you should see the following:

Your WordPress, your way

Each new WordPress release brings exciting Editor functionality, enhancing user capabilities. However, it’s equally important to customize the editing experience to meet your users’ specific needs.

The fifteen examples shared in this article are a great starting point, but there are countless other curation techniques. If you have unique ways of curating the Editor, please share your examples in the comments or submit a pull request to add them to the official documentation.

Often, the functionality already exists, but examples haven’t been created yet. If you need a feature that’s not available, consider opening an issue in the Gutenberg repository. The more customizable the Editor becomes, the more powerful it is.

For more information on Editor curation, check out these resources. The article on client-side filters, in particular, offers advanced examples of block “governance”:

Props to @greenshady and @bph for feedback and review on this post.

Categories: , ,

4 responses to “15 ways to curate the WordPress editing experience”

  1. Alberto PRado Avatar

    I applied all these tips to my blog, and now the block editor looks cleaner than ever. I guess that’s the amazing thing about WordPress: you can modify it. But why wouldn’t a lot of these things be disabled by default?

    1. Nick Diego Avatar

      WordPress generally defaults to enabling all that’s possible and then allows users/developers to turn things off they don’t need. It would be cool if many of these curation options were available in a user interface rather than just with code.

  2. Bjarne Oldrup Avatar

    These are very helpful tips. Thank you, Nick, for sharing.

    I’m currently using a combination of a custom theme.json file and the MRW Simplified Editor plugin (which, I assume, does some of the mentioned unregistering for me under the hood).

    Providing a simpler and “fool-proof” editing experience is crucial for my editors, not only for their productivity, but also to ensure some design consistency.

    In combination with pre-created patterns, and the brand-new pattern overrides, the road is paved for an intuitive and trouble-free editing experience, even for the newcomers, who don’t care for an explanation of the differences between margins and paddings 😉

    Pro tip: In your functions.php file, or your preferred code snippet plugin, you might be able to unregister unwanted stuff for selected roles only, still allowing the admin or design full access, but simplifying the block editor experience for editors and content creators.

    1. Nick Diego Avatar

      I took a look at the MRW Simplified Editor plugin, and you’re right, it applies many of these techniques under the hood. Very cool.

Leave a Reply

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