Every block in the Block Editor is contained within an HTML wrapper, which must have specific attributes to function correctly both in the Editor and on the front end. As developers, we can directly manipulate this markup, and WordPress offers tools like useBlockProps()
to modify the attributes added to a block’s wrapper.
Ensuring proper attributes to the block wrapper is especially important when using custom styling or features like block supports.
A block in WordPress can be defined with three distinct types of markup, each serving a unique role:
- Editor Markup: This is the visual representation of the block within the Block Editor. It’s defined using an
Edit
React component when the block is registered on the client side viaregisterBlockType
. - Save Markup: This markup is what gets saved to the database when the block’s content is saved. It’s specified through a
save
function, also provided toregisterBlockType
during block registration. If the block doesn’t utilize dynamic rendering, this saved markup is what will be displayed on the front end. - Dynamic Render Markup: When a block’s content needs to be generated dynamically, this markup comes into play. It’s defined server-side, either through a
render_callback
function inregister_block_type
or arender.php
file specified inblock.json
. If present, this markup overrides any saved markup and is used for the block’s front-end display.
For both the Edit
component and the save
function, it’s important to use a wrapper element that’s a standard DOM element (like a <div>
) or a React component that passes all additional props to native DOM elements. Using React Fragments (<Fragment>
) or the <ServerSideRender>
component won’t work for these wrappers.
Editor markup
The useBlockProps()
hook, provided by the @wordpress/block-editor
package, is used to define the outer markup of a block in the Edit
component.
This hook simplifies several tasks, including:
- Assigning a unique
id
to the block’s HTML structure. - Adding various accessibility and
data-
attributes for enhanced functionality and information. - Incorporating classes and inline styles that reflect the block’s custom settings. By default, this includes:
- The
wp-block
class for general block styling. - A block-specific class that combines the block’s namespace and name, ensuring unique and targeted styling capabilities.
- The
In the following example, the Editor markup of the block is defined in the Edit
component using the useBlockProps()
hook.
const Edit = () => <p { ...useBlockProps() }>Hello World - Block Editor</p>;
registerBlockType( ..., {
edit: Edit
} );
See the full block example of the code above.
The markup of the block in the Block Editor could look like this, where the classes and attributes are applied automatically:
<p
tabindex="0"
id="block-4462939a-b918-44bb-9b7c-35a0db5ab8fe"
role="document"
aria-label="Block: Minimal Gutenberg Block ca6eda"
data-block="4462939a-b918-44bb-9b7c-35a0db5ab8fe"
data-type="block-development-examples/minimal-block-ca6eda"
data-title="Minimal Gutenberg Block ca6eda"
class="
block-editor-block-list__block
wp-block
is-selected
wp-block-block-development-examples-minimal-block-ca6eda
"
>Hello World - Block Editor</p>
In a block’s Edit
component, use the useBlockProps()
hook to include additional classes and attributes by passing them as arguments. (See example)
When you enable features using the supports
property, any corresponding classes or attributes are included in the object returned by useBlockProps
automatically.
Save markup
When saving the markup in the database, it’s important to add the props returned by useBlockProps.save()
to the wrapper element of your block. useBlockProps.save()
ensures that the block class name is rendered correctly in addition to any HTML attributes injected by the block supports API.
Consider the following code that registers a block in the client. Notice how it defines the markup that should be used when editing the block and when the block is saved in the database.
const Edit = () => <p { ...useBlockProps() }>Hello World - Block Editor</p>;
const save = () => <p { ...useBlockProps.save() }>Hello World - Frontend</p>;
registerBlockType( ..., {
edit: Edit,
save,
} );
See the full block example of the code above.
The markup of the block on the front end could look like this, where the class is applied automatically:
<p class="wp-block-block-development-examples-minimal-block-ca6eda">Hello World – Frontend</p>
If you want to add any additional classes or attributes to the save
function of the block, they should be passed as an argument of useBlockProps.save()
. (See example)
When you add supports
for any feature, the proper classes get added to the object returned by the useBlockProps.save()
hook. Text and background color classes have been added to the Paragraph block in the example below.
<p class="
wp-block-block-development-examples-block-supports-6aa4dd
has-accent-4-color
has-contrast-background-color
has-text-color
has-background
">Hello World</p>
The example block that generated this HTML is available in the Block Development Examples repository.
Dynamic render markup
In dynamic blocks, where the front-end markup is rendered server-side, you can utilize the get_block_wrapper_attributes()
function to output the necessary classes and attributes just like you would use useBlockProps.save()
in the save
function. (See example)
<p <?php echo get_block_wrapper_attributes(); ?>>
<?php esc_html_e( 'Block with Dynamic Rendering – hello!!!', 'block-development-examples' ); ?>
</p>