Skip to main content

Using InnerBlocks

The <InnerBlocks /> component is one of the most powerful constructs in Gutenberg. It allows the insertion of child blocks, definition of templates, creation of complex layouts, and more.

HTML to Gutenberg offers full support for <InnerBlocks /> through a custom <inner-blocks> element, which provides a thin abstraction layer over InnerBlocks templates and configuration.

Open the live code editor

Edit this code to see the generated Gutenberg block files.

block.html
<section>
<inner-blocks templateLock>
<inner-block name="core/group">
<inner-block name="core/heading" level="3"></inner-block>
<inner-block name="core/paragraph">
<block-attribute name="content">
Lorem <strong>ipsum</strong>
</block-attribute>
</inner-block>
</inner-block>
</inner-blocks>
</section>

Adding InnerBlocks​

To define an editable block area using HTML to Gutenberg, use the <inner-blocks> element. By default, it allows inserting any available Gutenberg block, similar to using the <InnerBlocks /> component directly.

block.html
<section>
<inner-blocks></inner-blocks>
</section>

Defining an InnerBlocks template​

Use nested <inner-block> elements inside <inner-blocks> to define a default block structure.

block.html
<section>
<inner-blocks>
<inner-block name="core/heading"></inner-block>
<inner-block name="core/paragraph"></inner-block>
</inner-blocks>
</section>

You can also nest templates to create complex compositions, just like nesting elements in HTML.

block.html
<section>
<inner-blocks>
<inner-block name="core/group">
<inner-block name="core/heading"></inner-block>
<inner-block name="core/paragraph"></inner-block>
</inner-block>
</inner-blocks>
</section>

Default allowedBlocks​

By default, allowedBlocks is automatically inferred from the block types used in the template.

The inferred value of allowedBlocks for the example above would be:

["core/group", "core/heading", "core/paragraph"];

Overriding allowedBlocks​

To control which blocks users can insert inside the InnerBlocks zone, use the allowedBlocks attribute.

Allowing all blocks​

To allow all blocks to be inserted, set allowedBlocks to "all":

block.html
<section>
<inner-blocks allowedBlocks="all">
<inner-block name="core/group">
<inner-block name="core/heading"></inner-block>
<inner-block name="core/paragraph"></inner-block>
</inner-block>
</inner-blocks>
</section>

When <inner-blocks> does not define a template, all blocks are allowed by default.

Allowing specific blocks​

To restrict allowed blocks, pass a space-separated list of block names to allowedBlocks.

block.html
<section>
<inner-blocks allowedBlocks="core/group core/heading core/paragarph core/buttons">
<inner-block name="core/heading"></inner-block>
</inner-blocks>
</section>
info

HTML to Gutenberg will throw an error if any blocks used in the template are not listed in allowedBlocks.

Setting default block attributes​

HTML to Gutenberg supports 3 ways to define default block attributes, listed here in increasing order of priority:

1. As props on the <inner-block> element​

Pass simple values (strings, numbers, booleans) as props directly on the <inner-block> element.

block.html
<section>
<inner-blocks>
<inner-block
name="core/heading"
level="2"
content="Section title"
></inner-block>
</inner-blocks>
</section>

2. Using <block-attribute name value> syntax​

Use the <block-attribute> element with name and value attributes to explicitly set block attributes.

block.html
<section>
<inner-blocks>
<inner-block name="core/heading" level="2">
<block-attribute name="content" value="Section title"></block-attribute>
</inner-block>
</inner-blocks>
</section>

3. Using <block-attribute> children​

To embed rich content, such as HTML, within an attribute, omit the value attribute and place the content inside the element.

block.html
<section>
<inner-blocks>
<inner-block name="core/paragraph">
<block-attribute name="content">
This is some <strong>strong</strong> and <em>italic</em> text.
</block-attribute>
</inner-block>
</inner-blocks>
</section>

Locking InnerBlocks templates​

To prevent users from modifying the InnerBlocks structure, use the templateLock attribute.

block.html
<section>
<inner-blocks templateLock>
<inner-block name="core/group">
<inner-block name="core/heading"></inner-block>
<inner-block name="core/paragraph"></inner-block>
</inner-block>
</inner-blocks>
</section>

For more control, you can explicitly set one of the following values:

ValueDescription
"all" (default)Prevents all changes (insert, move, delete)
"insert"Disables block insertion
"contentOnly"Allows content editing only
"false"Disables template locking entirely

Using templateLock="false" is especially useful for nested InnerBlocks, as inner blocks inherit their locking state from the parent unless overridden.

Setting template orientation​

Use the orientation attribute to control the layout flow inside <InnerBlocks />.

ValueDescription
"vertical" (default)Blocks flow vertically
"horizontal"Blocks flow horizontally
info

This option affects block reordering behavior in the editor, not layout styles.

Considerations when using InnerBlocks​

Gutenberg currently supports only one <InnerBlocks /> per block. You can only use one <inner-blocks> element inside a single block template.

If you want to support multiple editable areas, split them into child blocks and include each as part of your layout.

Example: Hero Block with Two Zones​

Let’s build a Hero block that contains two editable regions:

  • A top section for a heading, paragraph, and buttons
  • A bottom section for additional text

Main custom/hero block​

The parent block defines the layout and includes two child blocks.

hero.html
<section class="hero">
<div class="hero__container">
<inner-blocks>
<inner-block name="custom/hero-top"></inner-block>
<inner-block name="custom/hero-bottom"></inner-block>
</inner-blocks>
</div>
</section>

Child custom/hero-top block​

hero-top.html
<div class="hero__top">
<inner-blocks>
<inner-block name="core/heading" level="1"></inner-block>
<inner-block name="core/paragraph"></inner-block>
<inner-block name="core/buttons"></inner-block>
</inner-blocks>
</div>

Child custom/hero-bottom block​

hero-top.html
<div class="hero__bottom">
<inner-blocks>
<inner-block name="core/paragraph"></inner-block>
</inner-blocks>
</div>

Final output​

When rendered, the resulting HTML will look like this:

<div class="hero">
<div class="hero__top">
<!-- Hero Top <InnerBlocks /> -->
</div>

<div class="hero__bottom">
<!-- Hero Bottom <InnerBlocks /> -->
</div>
</div>

You can now style each block using your preferred CSS approach.