Remove class=”wp-block-heading” From WordPress Heading Blocks
WordPress 5.9 started auto-adding class="wp-block-heading" to every <h1> … <h6> block. This filter strips it cleanly without disabling the block editor or rewriting core. Drop it in functions.php and every heading serialises as a plain <h2>.
The wp-block-heading class arrived with the Block API v2 migration to provide a style hook for block themes. If your theme already styles headings globally (most do), the class is noise — it bloats HTML, breaks existing CSS selectors that assume naked heading tags, and adds a diff line to every saved post. On gauravtiwari.org I ship around 2.1 KB of extra HTML across a long article for zero styling benefit. The filter below removes it at render time.
What this snippet does
- Strips
class="wp-block-heading"from allh1–h6output by the core heading block - Runs on the
render_blockfilter so it affects published output, not stored post content - Does not touch heading-blocks inside patterns or third-party blocks
- Saves roughly 20 bytes per heading — adds up fast on long-form content and archive pages
- Keeps anchor IDs and any custom classes the author added intact
Install and use
Drop into your child theme functions.php or a mu-plugin. No settings, no admin UI. Flush any full-page cache so stored HTML gets regenerated, otherwise the old class will sit in Flying Press / WP Rocket cache files until next rebuild.
<?php
/**
* Remove class="wp-block-heading" from core/heading block output.
*/
add_filter( 'render_block', function ( $block_content, $block ) {
if ( 'core/heading' !== ( $block['blockName'] ?? '' ) ) {
return $block_content;
}
// Remove standalone class attribute added by the block.
$block_content = preg_replace(
'/\sclass="wp-block-heading"/',
'',
$block_content
);
// Remove it when mixed with other classes.
$block_content = preg_replace(
'/(class="[^"]*?)\s?wp-block-heading\s?([^"]*?")/',
'$1$2',
$block_content
);
return $block_content;
}, 10, 2 );How it works
The render_block filter fires for every block during render, so we scope to core/heading only and run two regexes. The first handles the common case where the block has no other classes and the attribute is exactly class="wp-block-heading". The second handles the edge case where the author added an additional class (like has-text-align-center) so we strip only the targeted class without nuking the whole attribute. Anchor IDs and custom classes survive untouched.
Download and source
- Gist: gist.github.com/wpgaurav
- Bundled in Functionalities plugin as a toggle
- Reversible — remove the filter and stored HTML still contains the class, regeneration on next edit re-adds it