How to Build Nested Gutenberg Blocks (InnerBlocks) Without JavaScript

Some of the most useful blocks are containers: a card that holds a heading, text and a button; a tabs block that holds tab panels; a section with a fixed layout where editors only type the content. In Gutenberg this is called InnerBlocks, and it’s the best way to give editors freedom inside a design that can’t break.

Why container blocks

A block with fields in the sidebar is fine for short values. For real content (headings, paragraphs, lists, images), editors prefer typing directly on the page. A container block lets them use normal core blocks inside your layout.

The four settings that matter

SettingWhat it doesExample
Allowed blocksWhich blocks can go insideOnly core/heading, core/paragraph, core/buttons
TemplateBlocks inserted automaticallyA heading + paragraph + buttons, ready to fill in
LockStop adding, removing or moving inner blocksFixed card structure, editable text
ParentWhere *this* block may be placedA “Tab” block only inside a “Tabs” block

The React way

In a React block you render <InnerBlocks allowedBlocks={…} template={…} templateLock="all" /> in edit.js, and <InnerBlocks.Content /> in save.js. That means a build step and two components to keep in sync.

The PHP way with FanCoolo WP

In FanCoolo WP, turn on Inner Blocks Settings in the block editor and set:

  • Allowed Block Types: type block names like core/paragraph and press Enter. Leave empty to allow everything.
  • Block added by default: the template that appears when the block is inserted.
  • Lock Template: users can only edit the content of the blocks you provided.
  • Parent Block: restrict where this block can be inserted.

Then decide where the nested blocks render by placing the <InnerBlocks /> tag in your block’s PHP, inside your wrapper:

<section <?php echo get_block_wrapper_attributes( [ 'class' => 'feature-card' ] ); ?>>
  <div class="feature-card__icon"><?php echo esc_html( $attributes['icon'] ?? '' ); ?></div>
  <div class="feature-card__body">
    <InnerBlocks />
  </div>
</section>

In the editor it becomes the area where users add and arrange blocks; on the front end FanCoolo replaces it with the rendered inner blocks.

Parent and child blocks

Setting a Parent Block makes a child block, like core’s Button inside Buttons. There’s a catch in plain WordPress: many parents keep their own whitelist of allowed children, so declaring the parent alone can hide your block everywhere. FanCoolo makes the relationship work both ways: when you set a parent, it also adds your block to that parent’s allowed children, on the server and in the editor’s inserter.

Ideas

  • Feature card: icon from a sidebar field, heading and text as inner blocks.
  • Tabs: a Tabs container that only allows Tab children, each Tab holding any content.
  • Locked hero: fixed heading + text + buttons template, Lock Template on.

Starting from scratch? See how to create a custom Gutenberg block without React.

Container blocks without React

Container blocks without React

FanCoolo WP: InnerBlocks, templates, locking and parent/child blocks, configured in settings and rendered in PHP.