Creating WordPress block themes

This lesson is the first in a series of exercises to learn how to create block themes, also known as full site editing themes. You will learn about the minimum file requirements, theme setup, and file structure. I will also point out some important differences between classic themes and block themes.

By the end of this first lesson, you will have created an empty WordPress theme with support for full site editing. You will continue to build upon this theme over the next lessons:

  • In lesson two you will learn about the block markup that you will use in the theme templates.
  • In lesson three you will add functional templates such as single posts, pages, and archives.
  • In lesson four you will learn about the theme.json configuration file
  • In lesson five you will add settings and styles to theme.json.
  • Lesson six is in the writing stages and will guide you through how to continue building the theme in the Site Editor.

For this lesson, you will need your favorite code editor and a WordPress installation to test your theme on.

Estimated reading time: 6 minutes

Last updated

Introduction

The new Site Editor (Added in WordPress 5.9) will be one of your primary tools for creating WordPress block themes. For most block theme projects, that is where you will assemble, style, and edit blocks:

The Site Editor is a new tool for visual editing of all parts of the website, using blocks.

But the Site Editor will not expose all settings. Knowing how to make manual edits to the theme files is perhaps not as exciting, but it is good basic knowledge.

You need to install and activate a block theme before you can use the Site Editor. That is why the first two lessons in this chapter will be about manually creating a theme.

You can follow along and create a block theme with me, or use the “super quick start guide” and only use this page as a reference.

Super quick start guide for eager theme developers

1. Create a new theme folder inside wp-content/themes.
2. Create a style.css file for your new theme.
3. Create two new folders inside the theme folder: templates and parts.
4. Inside the parts folder, create an HTML file called header.html.
5. In header.html, add the following code: <!-- wp:site-title /--> and save.
6. Inside the templates folder, create an HTML file called index.html.
7. In index.html, add the block code below, and save:

<!-- wp:template-part {"slug":"header"} /-->

<!-- wp:query {"queryId":0,"query":{"perPage":3,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true,"taxQuery":null,"parents":[]},"displayLayout":{"type":"list"}} -->
<div class="wp-block-query">
<!-- wp:post-template -->
<!-- wp:post-title /-->
<!-- wp:post-date /-->
<!-- wp:post-content /-->
<!-- /wp:post-template -->
</div>
<!-- /wp:query -->

8: Activate the theme.

Step 1: Create the theme folder and style.css

You can expect that the theme setup will be more straightforward and require fewer files in the future. It is even possible that the only file you will need is the new theme.json configuration file. But let’s look at the theme file structure and block templates required to create block themes today.

Minimum requirements

Since version 6.0, WordPress no longer requires full site editing themes to include an index.php file. Instead, the minimum required files are style.css and an index.html file placed inside a folder called templates.

First, select a theme name and use the slug to create your new theme folder inside
wp-content/themes. If your theme name is “Lesson One”, your folder will be:

wp-content/themes/lesson-one

Create a style.css file in the root folder of the theme.
Full site editing themes use a standard style.css file header.
Copy and paste the following code into the file. Update the fields as needed.
The only required part of the file header is the theme name.

/*
Theme Name: Name of the theme.
Author: The name of the individual or organization who developed the theme.
Description: A short description of the theme.
Version: The version, written in X.X or X.X.X format.
Requires at least: The oldest main WordPress version supported, written in X.X format. 
Tested up to: The last main WordPress version the theme has been tested up to, i.e. 6.0. Write only the number.
Requires PHP: The oldest PHP version supported, in X.X format, only the number.
License: The license of the theme.
License URI: The URL of the theme license.
Text Domain: The string used for textdomain for translation. The theme slug.
*/

Start with an empty style.css file

Our theme will rely on block styles and the theme.json configuration file as much as possible.
I suggest starting with an empty style.css, except for the file header.
Using an empty style.css file is an excellent way to learn the strengths and limitations of theme.json.

Step 2: Add your first block template

Block templates are your base HTML files and just like PHP files in classic themes, they follow the WordPress template hierarchy.

/templates/index.html is the equivalent of index.php in a classic theme.
/templates/404.html is the equivalent of 404.php and so on.

For Gutenberg and WordPress to recognize that the active theme has support for the site editor, the theme must include an index.html file, and you must place it inside a folder called templates.

– Go ahead and create the folder and the empty index file before continuing to the next step. You will add content to this file in lesson three.

The template hierarchy -refresher

The following default, top-level templates are supported in the WordPress template hierarchy:

  • index
  • 404
  • archive
  • author
  • category
  • tag
  • taxonomy
  • date
  • embed
  • home
  • front-page
  • privacy-policy
  • page
  • search
  • single
  • singular
  • attachment

https://developer.wordpress.org/themes/basics/template-hierarchy/

Step 3: Create the theme.json configuration file

Theme.json is a configuration file for enabling and disabling block settings and for applying styles to blocks. I will describe how to use theme.json in detail in upcoming lessons, so do not worry if you are not familiar with this format yet.

In this lesson, you will add the layout setting: Block themes use this setting to specify the default content width and to support wide width, full width, left, center, and right alignments.

Create the theme.json file in the root folder, and copy and paste the following code:

{
        "version": 2,
	"settings": {
		"layout": {
			"contentSize": "840px",
			"wideSize": "1100px"
		}
	}
}

You have now set the content width to 840px and the wide width to 1100px.
These two values match the default widths in the editors, but you can adjust them.

 — There is no setting for full width because it is not needed: WordPress handles the width limitations by setting a max-width on the blocks using CSS.

Tip! 840px gives your website a high number of characters per line which can be difficult to read. Adjust the width to a comfortable reading length depending on your selected font family and font size.

Your theme structure should now look like this:

templates/
	index.html
style.css
theme.json

Step 4: Include functions.php and theme support (optional)

Themes do not require a functions.php file to work. You can include functions.php in your block theme if you need to enqueue stylesheets or JavaScript, add custom block styles and custom image sizes, or use hooks.

Create a new file in the root folder and name it functions.php.
Add the file header, and if you like, enqueue the style.css file for later use with wp_enqueue_style():

<?php
/**
 * Functions and definitions
 *
 * @link https://developer.wordpress.org/themes/basics/theme-functions/
 *
 * @package Lesson One
 * @since 1.0.0
 */

/**
 * Enqueue the style.css file.
 * 
 * @since 1.0.0
 */
function lesson_one_style() {
	wp_enqueue_style(
		'lesson-one-style',
		get_stylesheet_uri(),
		array(),
		wp_get_theme()->get( 'Version' )
	);
}
add_action( 'wp_enqueue_scripts', 'lesson_one_style' );

You do not need to enqueue the comment-reply script commonly used in classic themes, because the comments block enqueues this automatically.

Theme support

The following theme support is automatically enabled for block themes:
post-thumbnails, editor-styles, responsive-embeds, automatic-feed-links, html5 styles, and html5 scripts.

You do not need to include add_theme_support( 'title-tag' ) in the setup function, because WordPress already renders the title tag for full site editing themes.

Similarly, you do not need to register widget areas and menus and add theme support for a custom logo, custom header, or colors.

Adding theme support for wp-block-styles is optional. This file includes the combined CSS from the theme.scss file for individual blocks. For example, the padding when you add a background color to a group block and the default border of the quote block. Because this CSS is so opinionated, my recommendation is to not include it, but I will proved an example of how to add it:

if ( ! function_exists( 'lesson_one_setup' ) ) {
	function fse_setup() {
            add_theme_support( 'wp-block-styles' );
        }
}
add_action( 'after_setup_theme', 'lesson_one_setup' );

Templates are loaded in the body element

Templates and template parts use block markup and not plain HTML. One thing I get asked about frequently is how to make updates to the meta tags in the header of the theme.

When you create the templates in the next few lessons, you will find that the header template part does not include a <!DOCTYPE>,<html>, or <head>. There is also no <body> element.

WordPress already adds the necessary HTML elements and hooks. The complete code is:

<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
	<meta charset="<?php bloginfo( 'charset' ); ?>" />
	<?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>
<?php wp_body_open(); ?>

(template)

<?php wp_footer(); ?>
</body>
</html>

If you need to make changes to the meta tags, you need to use hooks and filters.

On the front, your templates and all your blocks are loaded in the <body> element, inside a <div> with the class wp-site-blocks. There is no way to remove this div.

<body>
<div class="wp-site-blocks">
...
</div>
</body>

This is added by the private function get_the_block_template_html().

Resources

If you want to learn more about the difference between a classic PHP based theme and block themes, there is an excellent section about this in the theme developer handbook, that includes a comparison table: