How I Create Block Themes

a man working on a web design on two different computer screens

Block themes are still a relatively new thing in WordPress.

The site editor is only two years old at this point and it’s been roughly a year since the beta label was removed, signaling that it’s at a point where it can be used on production sites.

Compared with the regular or classic themes that we’ve had almost since WordPress was created, block themes are still in their infancy.

And theme developers are still finding the sweet spot in how they create block themes for this new site editor world.

I’ve spent a lot of time working with the site editor and creating block themes almost since the site editor joined WordPress core with the 5.9 release, and I think I’ve almost got it down to a science.

So if you’re learning how to build block themes for WordPress, here’s the process I’ve been using to create themes for the Crosswinds Framework.

And if you want a starting point for your new block theme, you can check out the starter theme I’ve created on GitHub.

Start with the Basics

So like everything in web design and development, I start off with the basics. Which for me is basically the file structure for the theme.

I always have an assets folder where I put the CSS, JS, image and web font files for the theme. And I have a gulp build process for all of that (more on that in a bit). I’ll also have an includes directory where I can put in any extra PHP that I might need for the theme that I want outside of the functions.php file to keep it sane.

Now with block themes, I’ve added in a couple of new directories. The first is the patterns directory, which is where all of the patterns are loaded automatically by WordPress.

And then I have a parts directory for any template parts and a templates directory for all of the templates used on the site. And both of these directories house HTML files for templates and template parts.

Finally, the main directory houses the functions.php, style.css and theme.json files, which you need for a block theme (but not an index.php file any more).

Now, going back to the build process, I use a setup from the WP Rig starter theme that helps me compile and minify my CSS and JavaScript as well as minify any images. And it gives me a wonderful build function which allows me to create a clean zip file of the theme in an instant. 

That part is optional, but it really is nice to have that functionality when building themes.

But other than that, the file structure for a block theme is pretty straightforward.

Going Through the Theme.json File

Now, when I really get started with creating a new theme, I first start with the theme.json file.

This is something that really deserves its own blog post really. There’s just so much that you can do with this file that takes away from the need to write a bunch of CSS. And once you’ve really dived into it once or twice, it becomes pretty easy to understand and use.

But here’s a quick overview of what I do in the theme.json file.


First, I like to add in the fonts that I’m going to be using for the theme. I make sure to download each font and include it in the theme so that we don’t have to make a call to Google Fonts every time the theme loads a page.

If the theme is being built for a specific client, I will only include the fonts that are necessary for the website. If this is a commercial theme or a theme to be added to the WordPress Theme Directory, I’ll add around six to eight fonts to give users options for fonts they can use on their website.

As for the naming convention I use, if there’s only one font that’s going to be used for a variation, I’ll set the slug to be primary. If there are two fonts, the body font will get the secondary slug and the font for things like heading, navigation, buttons, etc. will get the primary slug.

I’m not sure if that’s the best practice for font naming. It’s worked for me so far, but I’m still open to changes if we theme developers figure out a better practice for that.

Finally with fonts, I set the different possible font sizes. I generally start with a regular size of 16px or 1rem (I’ve learned that rem is better than pixels) and work my way up from there. And I highly recommend using the fluid typography option you have with fonts and other spacing.


Next I move on to colors. These are a lot more simple than fonts. I add in base and contrast colors to be used as the background (base) and text (contrast) colors. After that I set the primary, secondary, tertiary and quaternary colors.

The primary and secondary colors have the correct contrast with the base color and the other two have the correct contrast with the contrast color.

The last color I add is a neutral gray color that can go with any of the other colors.

Finally, I’ll add in a bunch of different gradients involving those colors.

Other Settings

Next is spacing. This is something that I need to explore more, but below is an example of what I use for spacing in the theme.json file.

After that, I like to set the styles for different elements. This is where you can set the font settings for the body text as well as links, headings and buttons.

And finally there are the settings for each block. I generally like to add at least some styling to each of the core blocks and any third-party blocks I know will be vital to the design of the theme. But the choice is yours.

There is definitely a lot that you can do here in the theme.json file, so take your time going through it and setting all of the different settings you’re going to need for your theme or website.

Still Using CSS

While the theme.json file covers a lot of the CSS that’s needed for themes, it doesn’t cover everything, like hover or focus states and the like.

So for those things, I still use CSS. For example, I use CSS files to really define styles for buttons and any style variations for buttons I’m using in the theme. Also, I tend to have a file for any block styles I’m using, as I find it a bit easier to manage in actual CSS rather than the functions.php file.

It’s also a good place to add in styles for things like inputs and form fields, as those currently aren’t supported in the theme.json file.

And for good measure, I make sure in the build process that there’s a global stylesheet for the front end and an editor style for the block and site editors.

Still, the amount of CSS that I have to write is way, way down compared to PHP/Legacy/Classic themes.

Using the Block Editor to Create Patterns, Templates and Template Parts

My favorite part about creating block themes, though, is that I’m able to use the block editor to craft patterns, template parts and templates.

While I definitely enjoy writing PHP and CSS, being able to create things visually in the editor and then copy and paste them into files in the theme has made my theme-building process so much quicker. There’s not a whole lot of changing something here or there and then reloading the page to see how it looks and continuing to make adjustments from there.

Instead, I know exactly what it’s going to look like when I finally do copy over the code to the theme.

I will say that it does take a little bit of an adjustment when you’re first starting out, but once you get the hang of it, you can really build your themes so much quicker this way.

I will say that I try to put as much as I can into the patterns and then call those patterns in template parts and templates. The reason is because patterns are in PHP files where you can make any text strings translatable into other languages, which is extremely important if you’re building a theme to distribute.

Since template part and template files are HTML files, you can’t translate strings there. So if you’ve got, say, a query block for your archive page and it has read more text that needs to be translated, I would dump that into a pattern and then call that pattern in the archive template.

Keeping Blocks Out of Themes

Now, one thing I want to dive in on here is the debate over where custom blocks should go in your theme.

And the simple answer is that they should not be in your theme in any way, shape or form.

For starters, it will bloat your theme with extra JavaScript, CSS and PHP that aren’t needed in the theme. And that’s not good for performance.

But the bigger issue is that if a user uses your theme and adds in some of your custom blocks, but later changes themes, they are going to lose those blocks. And that might break their website. Blocks built in a theme don’t travel when a user changes themes.

It’s the same problem with putting custom post types or taxonomies or other functionality in a theme. That all goes away when a theme is changed, and that will break someone’s website.

This is why the WordPress Theme Directory guidelines keep themes from adding functionality. Themes are for design; plugins are for functionality.

If your theme needs custom blocks, build them in a blocks plugin that you can then recommend through the TGM Plugin Activation library. And don’t worry, the plugins directory review queue is in a much better place right now.

Thinking About Style Variations

And finally there are the style variations.

These are essentially their own theme.json files with their own color, font and other settings to allow a user to completely change the look and feel of their website with one click. This basically takes the color option feature a lot of theme developers would add to their themes and puts it into core.

And it’s a nice feature to have for users. Instead of having to change all of the colors, fonts and other settings by hand, they can just change them with a single click and then make minor adjustments as needed.

I usually save the style variations to the end as it’s typically the lowest priority when creating a theme. And right now I’m using style variations to just change the colors. Honestly, I do with there was a way to allow users to choose a color palette and font palette (for lack of a better word) independently of each other.

But with a new theme on the horizon (and also not having to try to pump out like six themes in a month’s time), I’m probably going to be playing around with the style variations even more.

What I Like About Building Block Themes

The biggest thing I like about building block themes is that they are so much quicker to build.

There’s not a whole lot that I have to do to get them started or to create amazing layouts. The vast majority of the CSS and PHP that I would have to write in the past is now replaced by being able to use the block editor to create those layouts and just copy it over to the theme files.

At one point I was able to build an entire child theme for the Crosswinds Framework in one week. That was unheard of for me to create a similar style of theme with classic themes.

Also, building visually is so much fun for me. I’m not having to run back and forth between my code editor and the browser to see how things look and what I need to change. Instead, I can tell how it looks right there in the editor. And making changes in a breeze (so long as there aren’t any major changes to how the block editor is laid out in core).

And finally, I like that I’m able to easily give theme users a lot of options for how they use the theme and create their website.

A big part of why I started creating the Crosswinds Framework is because I wanted to give users the ability to better use the WordPress site editor to create anything they wanted or needed (now, for my clients it’s a different story). And block themes make it so those users can really make their website their own without having to deal with HTML, PHP, CSS, etc.

Now, whether they end up messing up their website is a different story. But I’m of the mindset that giving the ability to customize their website from the dashboard is, overall, a pretty good move.

What I Dislike About Building Block Themes

On the other hand, it’s not all sunshine and rainbows when it comes to creating block themes. There are certainly problems and pitfalls that I run into.

First, documentation is still kind of lacking, especially compared to classic themes. It’s a completely understandable issue given just how long classic themes have been around and how new block themes are. And I know the documentation team is doing their best to get docs for creating block themes online as quick as they can.

It’s just an issue that will take a little bit of time to resolve.

Also there are a number of things that were easy with classic themes and are a bit harder to deal with in block themes. The biggest one I’ve found is dealing with search results. If I was building a website that had custom post types, I could easily create a search template that accounted for all of those post types since the template used PHP. But with block themes and HTML templates, it’s not so simple. In fact, this is the reason that I ended up building a post type search results block for the Crosswinds Blocks plugin to help anyone else who might have that same issue.

And finally there’s the issue of fonts. I love how easy it is to include fonts and with the coming font library feature where people can add any font they want to their website.

But trying to figure out how to set up a theme to be able to use fonts that a user chooses when it can be any theme is a bit of a challenge. I’ve done my best with the Crosswinds Framework themes, but I’m not sure if what I did will work for every situation.

Again, this is another thing that will likely get figured out as time goes on and we spend more time creating block themes.

What are Your Thoughts on Block Themes?

So now I’m curious about what you think about block themes. Have you built a block theme recently? What was your experience like? Do you think it’s better or worse than what we had before?

And if you haven’t yet, what’s holding you back? What questions do you have about creating block themes?

Be sure to drop any questions or answers you have in the comments section below. I would love to help you learn more about how you can build block themes either for the theme directory, to sell online or to create awesome websites for your clients.

Leave a Reply

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