How I Built It: Post Title Paragraph Option

, ,
a person working on a laptop that's showing the WordPress block editor

I love using the WordPress core blocks when building patterns, template parts and themes.

I don’t have to worry about building them from scratch or maintaining them. That’s already taken care of for me.

But I’ll admit there are times when those core blocks frustrate me. Like, as I talked about in a previous post, the fact that there isn’t a grid block in WordPress core is kind of frustrating, and I had to go out and create one from scratch (but, I admit, it was a lot of fun building that block).

With the development of Crosswinds Blocks v1.1, I ran into another issue with a core block. This time it was the post title or title block. And this led me down the rabbit hole of block filters in a JavaScript world.

So, here’s how I was able to add in a paragraph tag option for the title block in Crosswinds Blocks.

What the Need Was

While I use one of the heading levels for the title block, there are times when I would honestly prefer to just use a paragraph tag instead, especially with regards for accessibility.

Headings are used to denote sections of content. But when I’m displaying a blog post on the homepage in a blog section or have posts in a related posts section, I don’t really need a heading because it’s not really a section (although accessibility experts are absolutely free to correct me on this). Or if I’m just listing posts, I don’t really need them to be headings.

Instead, I just need a paragraph tag.

But, if you’ve used the block and site editors, you’ll know that that’s not possible with the title block. So now I had to figure out a solution to the problem.

What I Hoped the Solution Would Be

To be honest, I was really hoping the solution would be something simple. Maybe there was a filter that I could hook into that would allow there to be a paragraph option for the block. Or maybe there was a line or two of JavaScript that I just had to add.

After all, the site title block has a paragraph option. Why should it be that hard to give the title block that same option.

Unfortunately, after looking at the source code for the title block in the GitHub repository it became crystal clear that it was going to be more complicated than that.

There was no filter or line of code that I could add that would make that an option.

Instead this would have to be done the hard way with block filters all so I could, in effect, change just one line of code in the title block.

Researching the HeadingLevelDropdown Component

I quickly found that the component that controls the heading level for the heading, site title and title blocks is the HeadingLevelDropdown component.

If you’ve never used this component in your block development before, the good news is that it’s really straightforward for how to use it. Outside of the usual value and onChange parameters, there’s only one other parameter that you need to add: heading levels.

This controls what heading levels are available to be selected for the block. You can add in an array of numbers from 1 through 6 that correspond to that heading level, and you can add in 0 to add an option for the paragraph tag.

But it’s also an optional parameter, and the default is apparently just 1 through 6 and no zero. And of course, that’s what the title block uses.

Using Block Filters to Change the Post Title Block

The good news is that at this point block filters have been pretty well documented (compared to other parts of the site and block editors), so making changes wouldn’t be super hard.

The bad news is that it became obvious that I would have to recreate the entire block in order for this to work.

So I added a file inside of the block-customizations directory in the plugin and copied the code for the block into it. I also had to bring in a hook to see if the user can edit the block, but that was pretty easy.

I then made a change to create an array for the heading levels, 0 through 6 of course, and then added that array to the HeadingLevelDropdown component.

const HEADING_LEVELS = [ 0, 1, 2, 3, 4, 5, 6 ];

And finally, I added in the hook to the filter. And wouldn’t you know, that actually worked in the editor. Now to make that change in the footer.


You can view the entire file here in the GitLab repository.

Changing the Output on the Front End

The last thing I needed to do now is change the output on the front end to reflect the change in the editor.

For this, I needed to add a filter to the render_block hook. And then in that function, I checked to make sure we were looking at the post title block and then if we were, we needed to see if the heading level was 0. If it was, then we change the heading tag to a paragraph tag and display the block.

 * Updates the post title block to use the paragraph tag if that heading level is selected.
 * @param string $block_content      The content for the block.
 * @param array  $block              An array of information about the block.
 * @return string                    The updated content for the block.
public function update_post_title_block( $block_content, $block ) {
	if ( 'core/post-title' !== $block['blockName'] ) {
		return $block_content;

	if ( isset( $block['attrs']['level'] ) && 0 === $block['attrs']['level'] ) {
		return preg_replace(
			'/' . preg_quote( 'h0', '/' ) . '/',

	return $block_content;

And that worked surprisingly well!

So now if you choose a paragraph level for the title block while using Crosswinds Blocks, you’ll be able to turn it into a paragraph.

What I Hope to See in the Future

In the future, I hope that this feature in the Crosswinds Blocks plugin is no longer needed.

It would be great if the WordPress core title block just simply added in a paragraph option so that it was available for everyone. I’m not really sure why it isn’t like that in the first place, especially since the site title block has that option, as I mentioned before.

But until then, the Crosswinds Blocks plugin will have this option for anyone who needs it.

Leave a Reply

Your email address will not be published. Required fields are marked *