By default a block renders its own markup and nothing else. Inner Blocks turn a block into a container — a block that holds other blocks, the way core/columns holds columns or core/group holds anything you drop inside.
You configure all of this from the Inner Blocks Settings panel in the block editor — no
block.json editing required.
Enabling Inner Blocks
In the block editor, switch on the Inner Blocks Settings toggle. This reveals four controls:
Allowed Block Types
Restrict which blocks users can place inside your container. Type a block name (e.g.
core/paragraph, core/heading, fancoolo/button) and press Enter to add it.
Leave it blank to allow all blocks.
Block added by default
The template — blocks that are inserted automatically when your block is added to a page. Add block names here and they appear pre-filled, ready to edit. If you set Allowed Block Types, only those names are suggested.
Pre-filled starting items
A starting item can also carry its own content, such as a title or a price. You don't set this content in the editor. It comes with blocks that were prepared with it, for example blocks imported from an export file. Such a block inserts several items that are already filled in, each with its own sample text, so editors replace text instead of starting from empty items.
Editing the list of starting blocks keeps this content. If you remove an item from the list, its content goes with it.
Lock Template
A select that decides what editors may do with the blocks inside this block.
| Option | What editors can do |
|---|---|
| None (unlocked) | Add, remove, move and edit blocks. This is the default. |
| All: no adding, removing or moving | Edit the content of the blocks only. The structure is fixed. |
| Insert: no adding or removing, moving allowed | Reorder and edit the blocks, but not add or remove any. |
| Content only: edit text and media only | Change text and media. Nothing else, including block settings, can be changed. |
Use it together with Block added by default to give editors a fixed structure.
Blocks that used the old on/off switch keep working. A locked block is now set to All, which is what the switch did before, and an unlocked block stays on None.
Parent Block
Restricts where this block can be inserted. See the Parent Block section below — it behaves differently from the other three settings.
Rendering Inner Blocks
Enabling the setting tells WordPress your block accepts children, but you still decide where
they appear. In your Content, drop an <InnerBlocks /> tag wherever the nested blocks should
render:
<div <?php echo get_block_wrapper_attributes(); ?>>
<div class="my-container">
<InnerBlocks />
</div>
</div>
<InnerBlocks /> does double duty: in the editor it becomes the insertion area where users add
and arrange nested blocks, and on the front end FanCoolo replaces it with the rendered HTML of
those blocks. Without it, the inner blocks have nowhere to appear — they're saved but never shown.
The tag is case-insensitive and self-closing (<InnerBlocks />). Add it once; place it inside your
wrapper markup, not outside it.
Parent Block
The Parent Block field does the opposite of Allowed Block Types: instead of saying "these blocks may go inside me," it says "I may only be placed inside these parents."
For example, set a block's Parent Block to core/buttons and it becomes a child of the Buttons
block — like the native core/button.
Why this needs FanCoolo to do extra work
In plain WordPress, declaring a parent is only half the relationship. A parent like core/buttons keeps its own whitelist of allowed children (it only allows core/button). So if you only declared the parent, your block would be hidden everywhere — the parent still refuses it.
FanCoolo makes the relationship bidirectional automatically. When you set a Parent Block, FanCoolo also adds your block to that parent's list of allowed children, so it actually shows up in the parent's inserter — no custom code needed.
This applies both on the server and inside the editor's inserter (core blocks register their allowed children in JavaScript, which a PHP setting alone can't reach — FanCoolo handles both layers).
Note: FanCoolo only extends a parent that already restricts its children. A parent that allows everything is left untouched, so declaring it as a parent never accidentally narrows what that parent can otherwise hold.