MW
Tutorial

WordPress 7.0 for Block Developers: Breaking Changes

WordPress 7.0 enforces the iframed editor, broadens contentOnly mode, and drops PHP 7.3. Here are the breaking changes block and plugin developers must fix before users upgrade.

advanced 25 min May 20, 2026
You maintain a plugin or theme that registers blocks or patterns Comfortable editing block.json and plugin headers

WORDPRESS 7.0 FOR BLOCK DEVELOPERS

Most of WordPress 7.0 is additive — new APIs, new blocks, new screens. This tutorial is about the part that is not. There are a handful of changes in 7.0 that can break an existing block plugin, and they will surface the moment your users click “Update.”

If you maintain anything that registers blocks, patterns, or relies on theme support flags, read this one carefully.

The breaking changes at a glance

Block API version
Wrong
"apiVersion": 2
Right
"apiVersion": 3
If any block in a post is below API v3, WordPress removes the editor iframe for that post — you lose the isolation 7.0 enforces.
contentOnly content attributes
Wrong
{ "heading": { "type": "string" } }
Right
{ "heading": { "type": "string", "role": "content" } }
Inside a contentOnly pattern, attributes without role:content are hidden in List View and become uneditable.
Minimum PHP version
Wrong
Requires PHP: 7.2
Right
Requires PHP: 7.4
WordPress 7.0 drops PHP 7.2 and 7.3. Core now requires 7.4 — your plugin header should say so too.
HTML5 script theme support
Wrong
add_theme_support( 'html5', [ 'script' ] )
Right
// 'script' removed — enqueue scripts the standard way
The 'script' value of html5 theme support is deprecated and removed in 7.0.

1. The iframed editor is now enforced

WordPress has rendered the post editor inside an iframe for a while, but it was conditional. In 7.0 it becomes a rule: the iframed editor is enforced when every Block API block inserted into the post uses version 3 of the API or higher.

If even one block is still on API v2 (or lower), WordPress removes the iframe for that post to preserve backward compatibility. That sounds harmless, but it means a single outdated block silently downgrades the editing environment for the whole post — and your block may behave differently inside the iframe versus outside it (styles, global scope, measurement).

The fix is straightforward and overdue: move your blocks to "apiVersion": 3 in block.json, and test them inside the iframe.

2. contentOnly mode is applied more broadly

This is the change most likely to catch block developers off guard. contentOnly editing mode — where only the content of inner blocks is editable, not their structure — is now the default for patterns that previously relied on unrestricted editing of their inner blocks.

The consequence for custom blocks: if your block can end up nested inside a contentOnly pattern, every attribute that represents editable content needs "role": "content" in its block.json definition. Without it, that attribute is hidden in List View and cannot be edited.

{
  "attributes": {
    "heading": {
      "type": "string",
      "source": "html",
      "selector": "h2",
      "role": "content"
    }
  }
}

If broader contentOnly behaviour is wrong for your use case, 7.0 gives you two opt-outs: a new disableContentOnlyForUnsyncedPatterns setting, or the block_editor_settings_all PHP filter — both let you exempt unsynced patterns from contentOnly mode.

3. PHP 7.2 and 7.3 are gone

WordPress Core’s minimum PHP version is now 7.4. Versions 7.2 and 7.3 are no longer supported.

Two actions: update your plugin’s Requires PHP: header to 7.4, and — if your code still carries polyfills or branches for 7.2/7.3 — you can now delete them. PHPMailer has also been updated to 7.0.2, which includes a Sender-address bug fix; if you touch mail directly, retest.

4. HTML5 ‘script’ theme support removed

The script value passed to add_theme_support( 'html5', ... ) is deprecated and removed in 7.0. If a theme you maintain still declares it, drop that array entry. Scripts should be enqueued through the standard wp_enqueue_script() path — which is how nearly everyone does it already.

5. The default new-user role selector changed

For security, 7.0 removes the Administrator and Editor roles from the default-role selector under Settings → General. Site Health now raises an alert if one of those high-privilege roles was selected as the default before the update.

If your plugin programmatically sets or reads the default role, account for this. There is a new default_role_dropdown_excluded_roles filter to change which roles are excluded, if you have a legitimate reason to.

6. Block Hooks moved to the REST controller

A quieter change: the Block Hooks logic for content-like custom post types has moved out of individual post-type filters and into the REST controller. If your plugin hooks into Block Hooks behaviour for a CPT, verify it still fires where you expect.

Your 7.0 audit, in short

If you do nothing else before your users upgrade, do these four:

  1. Move every registered block to "apiVersion": 3 and test it inside the iframe.
  2. Add "role": "content" to content attributes on any block that can be nested in a pattern.
  3. Bump Requires PHP: to 7.4.
  4. Remove html5 script theme support if a theme declares it.

What’s next

That is the defensive work. The next tutorial is the fun part — the new blocks and design tools in 7.0: block-level custom CSS, the new Headings and Breadcrumbs blocks, the Gallery lightbox, and the expanded dimensions controls.

You've completed this tutorial!

Get the next one in your inbox. Practical tips, no fluff.

Subscribe

Get weekly notes in your inbox

Practical tips, tutorials and resources. No spam.