Navigation block font-size propagation fixed; transform variation targeting added
v7.1
In this post, you will find dev notes for smaller changes to the editor in WordPress 7.1.
Table of contents
Blocks
Navigation block stops propagating font-size to child items
The Navigation block will no longer forcefully propagate its font-size configurations down to the markup of individual child blocks (core/navigation-link, core/navigation-submenu, core/page-list, and core/home-link).
Currently, font size is propagated to every navigation item. Because relative units multiply against their parent container’s computed size, this caused extreme compounding (e.g., 1.5em → 2.25em → 3.375em), severely breaking the layout of deeply nested dropdown menus.
By removing the explicit application on child items, the Navigation block now safely relies on standard CSS text inheritance. This fixes an issue where the editor canvas and the frontend displayed mismatched typography sizes when child links had their own explicit font sizes overridden by parent propagation.
As for backwards compatibility, theme developers can restore the legacy font-size propagation behavior by applying the following filter in their functions.php:
/**
* Restores font size classes on Navigation child blocks.
* Use this if your theme targets has-{slug}-font-size on nav items directly.
*/
function restore_nav_item_font_size( $block_content, $parsed_block, $block ) {
$context = $block->context;
$has_named_font_size = array_key_exists( 'fontSize', $context );
$has_custom_font_size = isset( $context['style']['typography']['fontSize'] );
if ( ! $has_named_font_size && ! $has_custom_font_size ) {
return $block_content;
}
$target_tag = 'core/page-list' === $block->name ? 'UL' : 'LI';
$processor = new WP_HTML_Tag_Processor( $block_content );
if ( ! $processor->next_tag() || $target_tag !== $processor->get_tag() ) {
return $block_content;
}
if ( $has_named_font_size ) {
$processor->add_class( sprintf( 'has-%s-font-size', $context['fontSize'] ) );
} elseif ( $has_custom_font_size ) {
$existing_style = $processor->get_attribute( 'style' ) ?? '';
$font_size_style = sprintf(
'font-size: %s;',
wp_get_typography_font_size_value(
array( 'size' => $context['style']['typography']['fontSize'] )
)
);
$processor->set_attribute( 'style', $existing_style . $font_size_style );
}
return $processor->get_updated_html();
}
add_filter( 'render_block_core/navigation-link', 'restore_nav_item_font_size', 10, 3 );
add_filter( 'render_block_core/navigation-submenu', 'restore_nav_item_font_size', 10, 3 );
add_filter( 'render_block_core/home-link', 'restore_nav_item_font_size', 10, 3 );
add_filter( 'render_block_core/page-list', 'restore_nav_item_font_size', 10, 3 );
References:
- Navigation block: Stop font size setup propagation to children blocks (causes font size multiplication issue!)
- Prevent font-size propagation in Navigation items causing
emcompounding
Targeting Block Variations in Block Transforms
It’s now possible to target a specific block variation in a block transform, via the optional variationName property:
transforms: {
to: [
{
type: 'block',
blocks: [ 'core/group' ],
variationName: 'group-grid',
transform: ( attributes, innerBlocks ) => {
return createBlock(
'core/group',
{
...attributes,
layout: { type: 'grid' },
},
innerBlocks
);
},
},
],
}
For programmatic transforms, switchToBlockType now accepts the target variation name as an optional third argument:
switchToBlockType( blocks, 'core/group', 'group-grid' );
References:
Stabilize cloneSanitizedBlock and sanitizeBlockAttributes
The @wordpress/blocks package and wp.blocks global have two functions, __experimentalCloneSanitizedBlock and __experimentalSanitizeBlockAttributes.
These functions will continue to work in WordPress 7.1, but they will now log deprecation messages to the console. The functions have been replaced with stable versions that do not have the __experimental prefix.
Developers should replace any usage of __experimentalCloneSanitizedBlock with cloneSanitizedBlock and __experimentalSanitizeBlockAttributes with sanitizeBlockAttributes.
References:
Updated Markdown parsing library
@wordpress/blocks replaced showdown with marked for parsing pasted Markdown. The parser is internal to pasteHandler() and was never exported, so no code changes are needed.
Output should be equivalent, but edge cases now follow the CommonMark and GFM specs. Consumers calling pasteHandler() directly should re-test representative Markdown input against the blocks it produces.
References:
Mobile multi-selection and event handler compatibility
From WP 7.1, the paragraph block will support native iOS and Android multi-selection. To achieve this, the block opts in to moving the contenteditable wrapper from the block to the canvas wrapper. See the original pull request for more information.
The one consequence of this is that editing event handlers (key, input, and composition events) no longer fire on the block but rather on the canvas element. This only affects the paragraph block right now (which has been adapted), and will also affect other text blocks in the future such as heading, list item, etc. It will not affect non-core blocks unless they opt in when the API becomes available. It will, however, affect filters adding props to the paragraph block. For example:
addFilter(
'editor.BlockListBlock',
'my-plugin/track-keys',
( BlockListBlock ) => ( props ) => (
<BlockListBlock
{ ...props }
wrapperProps={ {
...props.wrapperProps,
onKeyDown: ( event ) => {
...
},
} }
/>
)
);
We make sure to cover such cases by calling the listeners with a pseudo-SyntheticEvent. Any handler added this way should still be called, but there might be very subtle changes, such as the native event target pointing to the canvas rather than the block element. The target for the synthetic event has been adjusted to be the block.
References:
- Add an `editableRoot` block support for native cross-block selection
- Redirect editing events to extension handlers under editableRoot
Editor
Template parts can opt out of content-only editing
WordPress 7.1 introduces a disableContentOnlyForTemplateParts editor setting, letting themes and plugins restore standard block editing for Template Parts instead of the content-only editing used by default.
Set it via the block_editor_settings_all filter in PHP:
add_filter( 'block_editor_settings_all', function ( $settings ) {
$settings['disableContentOnlyForTemplateParts'] = true;
return $settings;
} );
Or at runtime from JavaScript:
wp.data.dispatch( 'core/block-editor' ).updateSettings( {
disableContentOnlyForTemplateParts: true,
} );
When the editor is in template-locked rendering mode, content-only editing for Template Parts is always disabled regardless of this setting.
There is no impact on backward compatibility: leaving the setting unset preserves the existing default behavior.
For a session-only toggle while editing, the command palette also offers an “Enable/Disable content-only editing for patterns and template parts” command.
References:
- Block Editor:
disableContentOnlyForTemplatePartscannot be overridden via PHP filter - Block Editor: Allow overriding
disableContentOnlyForTemplatePartssetting
Global Styles
Block-level preset classes now match root-level specificity
WordPress 7.1 lowers the CSS specificity of the preset utility classes (.has-*-color, -background-color, -border-color, -gradient-background, -font-size, -font-family) generated for block-level presets, so they match the specificity of top-level (root) presets.
Presets defined at the block level, that is, via theme.json settings.blocks.<block> or the wp_theme_json_data_* filters, used to prepend the block selector to the preset class, raising its specificity above top-level presets.
The block selector is now wrapped in :where(), which contributes no specificity.
Before:
.has-accent-color { color: … !important; } /* top level: 0-1-0 */
p.has-accent-color { color: … !important; } /* block level: 0-1-1 */
.wp-block-group.has-accent-color { color: … !important; } /* block level: 0-2-0 */
After:
:where(p).has-accent-color { color: … !important; } /* 0-1-0 */
:where(.wp-block-group).has-accent-color { color: … !important; } /* 0-1-0 */
Scoping is unchanged. The rule still only matches the class on/within that block. Top-level presets are unchanged.
The reason for the change is that block-level presets out-ranking top-level ones was inconsistent and broke the responsive style states also landing in 7.1. Preset classes and responsive state styles both use !important, so specificity picked the winner. For example, a block-level palette colour set for Desktop overrode one set for Mobile. At equal specificity the responsive rule now wins on source order, as intended.
Affected are themes and plugins that register block-level presets and depend on their former, higher specificity. For example custom CSS written to slot between a top-level and a block-level preset. Such rules now tie block-level presets at 0-1-0.
The risk of regression is relatively contained because:
- presets flow through CSS variables, so only collision tie-breaks change, not rendered values.
- only
!importantauthor CSS ever competed with presets, and the drop is a single component in each case:0-1-1to0-1-0for element-based block selectors,0-2-0to0-1-0for class-based ones. :where()is already used throughout Gutenberg to manage specificity.- Realistic collisions are dominated by the responsive-states bug this fixes. Responsive states are new to 7.1.
References:
- 7.1 Bug when using JSON filter for text colors in Responsive style states for blocks
- Theme JSON: Level block-level preset class specificity with :where()
Core Data
Non-paginated entities now return all records
Several REST API endpoints ignore the page and per_page collection parameters and always return the entire collection. getEntityRecords() applied client-side pagination to every entity, slicing responses to the default per_page of 10 and ignoring remaining records. That was a bug.
The unintended behavior has been corrected: slicing now only happens for entities that declare supportsPagination: true, and everything else returns the full collection.
The common per_page: -1 workaround is no longer necessary, though passing it remains harmless. If you were getting a short list back from one of these entities, you’ll now get all of them, so take a look anywhere you render or loop over the results without setting your own limit. Custom entities backed by a non-paginated REST route should declare supportsPagination: false.
References:
Deprecating legacy editor packages
@wordpress/nux: Now a no-op compatibility package
Starting in WordPress 7.1, the @wordpress/nux package becomes a no-op compatibility package.
The package has been deprecated since WordPress 5.4. It remains available so existing imports and script dependencies do not break, but it no longer displays tips or guides.
If you still rely on NUX for onboarding, migrate to the Guide component from @wordpress/components instead.
References:
@wordpress/reusable-blocks: Public APIs now log deprecation warnings
The @wordpress/reusable-blocks package components and data APIs will log deprecation warnings starting from WordPress 7.1.
The package only exposed experimental APIs, and it hasn’t been used by the core since 2023. If your code needs to fetch or update Synced Patterns (formerly known as Reusable Blocks) on the client side, use the standard core entity methods.
This deprecation prepares the packages for a no-op backward compatibility update, similar to @wordpress/nux.
References:
Props to @ellatrix, @isabel_brison, @mamaduka, @ramonopoly, @sarthaknagoshe2002, @talldanwp, and @0mirka00 for content, and to @ramonopoly and @tyxla for review.
Fetched August 4, 2026

