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 all h1h6 output by the core heading block
  • Runs on the render_block filter 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

FAQs

Leave a Comment