Build Gutenberg Block Styles for WordPress Headings

You want to build and style a Gutenberg block style in WordPress and assign it to the Heading block. Editors then pick a headline look from the Styles panel, the same way they switch a button between Fill and Outline. They don’t have to type classes into Additional CSS or copy a styled block around. This post assumes “headline” means the core Heading block (core/heading), since that’s the block used for headlines in posts, pages and templates.

The snippet below registers three heading styles: an accent bar under the text, a small uppercase eyebrow label and a marker-pen highlight. Each one ships its own CSS, which WordPress loads in the editor and on the front end. It needs no build step, no JavaScript and no theme.json changes.

The snippet

Put it in a small plugin, an mu-plugin or your theme’s functions.php.

<?php
/**
 * Plugin Name: DPC Heading Block Styles
 * Description: Extra block styles for the core Heading block.
 */

add_action( 'init', 'dpc_register_heading_block_styles' );

function dpc_register_heading_block_styles(): void {
	$styles = [
		'dpc-underline' => [
			'label' => __( 'Underline accent', 'dpc' ),
			'css'   => '
.wp-block-heading.is-style-dpc-underline::after {
	content: "";
	display: block;
	width: 3rem;
	height: 0.25rem;
	margin-top: 0.4em;
	border-radius: 2px;
	background: var(--wp--preset--color--primary, currentColor);
}
.wp-block-heading.has-text-align-center.is-style-dpc-underline::after { margin-inline: auto; }
.wp-block-heading.has-text-align-right.is-style-dpc-underline::after { margin-inline-start: auto; }',
		],
		'dpc-eyebrow'   => [
			'label' => __( 'Eyebrow', 'dpc' ),
			'css'   => '
.wp-block-heading.is-style-dpc-eyebrow {
	font-size: 0.875rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	opacity: 0.8;
}',
		],
		'dpc-highlight' => [
			'label' => __( 'Highlight', 'dpc' ),
			'css'   => '
.wp-block-heading.is-style-dpc-highlight {
	text-decoration-line: underline;
	text-decoration-color: var(--dpc-highlight-color, #ffe58a);
	text-decoration-thickness: 0.35em;
	text-underline-offset: -0.2em;
	text-decoration-skip-ink: none;
}',
		],
	];

	foreach ( $styles as $name => $style ) {
		register_block_style(
			'core/heading',
			[
				'name'         => $name,
				'label'        => $style['label'],
				'inline_style' => $style['css'],
			]
		);
	}
}

How it works

  • register_block_style() adds a style to an existing block. The name becomes the CSS class is-style-{name} on the block’s wrapper, so dpc-underline shows up as is-style-dpc-underline.
  • label is the text editors see in the Styles panel of the block sidebar, and in the preview that appears when they hover over it.
  • inline_style is attached to the block’s stylesheet with wp_add_inline_style(). WordPress prints it in the editor canvas and on the front end, so what editors see while writing is what visitors get.
  • Every selector starts with .wp-block-heading, the class WordPress puts on every Heading block. That keeps the styles from reaching other blocks that might share the same is-style-* class.
  • The colours fall back to your theme.json presets where possible (--wp--preset--color--primary) and to currentColor when the preset doesn’t exist. That way a style still works on a theme with different palette slugs.

Customise it

  • Add another style: copy one entry in $styles, give it a new key and write CSS that targets .wp-block-heading.is-style-{your-key}.
  • Use a stylesheet file instead of inline CSS: register a stylesheet with wp_register_style() and pass its handle as style_handle in place of inline_style. This is easier to maintain once the CSS grows past a few rules.
  • Apply it to the Post Title block too: call register_block_style() again with core/post-title and add .wp-block-post-title.is-style-{name} to the selectors. That gives template headlines the same looks.
  • Change the highlight colour per site: set --dpc-highlight-color in your theme CSS, or in theme.json custom CSS, without touching the snippet.
  • Load your own editor-only tweaks: if a style needs extra rules inside the editor only, see CSS In Gutenberg editor.

Gotchas

  • Don’t rename a style after editors use it. The class is saved in the post content. If you rename dpc-underline, existing headings keep the old class and silently lose their styling.
  • A block can have only one block style at a time. If editors need an eyebrow with a highlight, register a combined style instead of expecting them to stack.
  • Inline font sizes win. If an editor sets a custom font size on the block, the inline style attribute overrides the eyebrow’s font-size. Preset sizes chosen from the font-size picker also take priority.
  • Removing core block CSS removes these styles too. WordPress attaches inline block-style CSS to the block’s own stylesheet (or wp-block-library). If you remove the Gutenberg block library CSS, move these rules into your theme stylesheet.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You’ll also get DPlugins product updates. No spam, and you can unsubscribe anytime.

// newsletter

Three tested WordPress snippets a week

Blocks, security, performance, Tailwind, PHP and React. Copy, paste, ship. You'll also get DPlugins product updates. No spam, and you can unsubscribe anytime.