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
namebecomes the CSS classis-style-{name}on the block’s wrapper, sodpc-underlineshows up asis-style-dpc-underline. labelis the text editors see in the Styles panel of the block sidebar, and in the preview that appears when they hover over it.inline_styleis attached to the block’s stylesheet withwp_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 sameis-style-*class. - The colours fall back to your theme.json presets where possible (
--wp--preset--color--primary) and tocurrentColorwhen 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 asstyle_handlein place ofinline_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 withcore/post-titleand 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-colorin 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
styleattribute overrides the eyebrow’sfont-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.