Creating block-based WordPress themes

Level: Beginner

For this full site editing lesson you will need:

  • A WordPress installation with some test content and the Gutenberg plugin.
  • Your favorite code editor

Estimated reading time: 6 minutes

This lesson has been updated for Gutenberg version 10.3 on April 7 2021

Once the site editor is completed, the editor will be your primary tool for creating block-based WordPress themes. That is where you will assemble, style, and edit blocks.
But some settings will not be exposed in the UI. Knowing how to make manual edits to the theme files is perhaps not as exciting, but it is good basic knowledge.

Before you can use the site editor to create new block templates, a theme with support for full site editing needs to be installed and activated. This is why the first lesson in this section will be about manually creating a basic theme that you can build upon.

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

Super quick start guide for eager theme developers

First, you must enable Gutenberg.

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

<!-- wp:template-part {"slug":"header"} /-->
<!-- wp:query {"queryId":1,"query":{"perPage":3,"pages":1,"offset":0,"postType":"post","categoryIds":[],"tagIds":[],"order":"desc","orderBy":"date","author":"","search":"","sticky":"exclude","inherit":true},"layout":{"type":"list"}} -->
<!-- wp:query-loop -->
<!-- wp:post-title /-->
<!-- wp:post-date /-->
<!-- wp:post-content /-->
<!-- /wp:query-loop -->
<!-- /wp:query -->

10: Activate the theme.

Theme setup today and in the future

You can expect that in the future, the theme setup will be simpler and require fewer files.
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 that are needed for creating a block-based theme today.

Minimum requirements

Select a name for your theme and use the theme slug to create your theme folder.
If your theme name is “FSE”, short for full site editing, your theme folder will be:

wp-contents/themes/fse/

These first two files are required for any theme to be activated:

index.php
Create a new blank file in the root folder and name it index.php.
Without index.php, the WordPress installation will consider the theme broken.
The only reason to include this file is to make sure that the theme can be activated.

style.css
Create a style.css file inside the root folder.
The file header provides the WordPress installation with information about the theme.
Full site editing themes use a standard style.css file header:

/*
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. 5.4. 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.
*/

What about the styles? Our theme will rely on the block styles as much as possible.
But sometimes that is not enough, and if you want to include a CSS reset you need to enqueue that separately or in style.css.

I am going to add a minimal, less opinionated reset for now. If we do not add body { margin: 0; }, the browsers will not display our full-width blocks correctly.
Copy this into the style.css file:

body {
	margin: 0;
	overflow-x: hidden;
}

* {
	box-sizing: border-box;
}

/* Elements */
img {
	max-width: 100%;
	height: auto;
}

Functions.php is not required for a theme to work. But it can be used to cover things that full site editing can not do yet.
Include this file if you need to: Enqueue styles, JavaScript or fonts, create block patterns, or use hooks that are not available for blocks.

Create a new file in the root folder and name it functions.php.
Add the file header and enqueue the style.css file:

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

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

I am choosing not to enqueue the comment-reply script. This is because the comments block enqueues this automatically from version 10 of Gutenberg.

Theme support

Our theme will have a setup function for adding theme support, but it will have fewer items
than you might see in a classic PHP based theme.

  • add_theme_support( 'automatic-feed-links' );
  • add_theme_support( 'responsive-embeds' );
  • add_theme_support( 'editor-styles' ); -If you are using editor styles.
  • add_theme_support( 'wp-block-styles' );

I have not used add_theme_support( 'title-tag' ); because it is already included with full site editing.

In a full site editing theme the featured image is a block, so you do not need to add theme support for post thumbnails.
If you want to add specific image sizes or set the post thumbnail size, you can still do that in the setup function.

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

if ( ! function_exists( 'fse_setup' ) ) {
	function fse_setup() {
            add_theme_support( 'automatic-feed-links' );
            add_theme_support( 'responsive-embeds' );
            add_theme_support( 'editor-styles' ); // Only if you are using editor styles.
            add_theme_support( 'wp-block-styles' );
        }
}
add_action( 'after_setup_theme', 'fse_setup' );

Later you will add support for wide and full width blocks and features like the color palette, gradients, and font sizes via the experimental-theme.json file.

Block templates

For Gutenberg and WordPress to recognize that the active theme has support for full site editing, the theme must include an index.html file and it must be placed inside a folder called block-templates.

Block templates are your base files. They are HTML files and they must be placed inside a folder called block-templates.
Block templates follow the WordPress template hierarchy:
/block-templates/index.html is the equivalent of index.php in a classic theme.
/block-templates/404.html is the equivalent of 404.php, and so on.

Block template parts

Block template parts are not required, but they are available to theme authors to help us
structure the theme with reusable, smaller parts.
A template part is a block that is a container for other blocks. They are HTML files and they must be placed inside a folder called block-template-parts.
/block-template-parts/header.html would be the equivalent of header.php.

The template hierarchy -refresher

The following default 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,
and attachment.

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

Inside the theme folder, create the two new folders: block-templates and block-template-parts.
Your theme structure should now look like this:

/wp-content/themes/fse/
index.php
functions.php
style.css
block-templates/
block-template-parts/

You can download the empty theme from GitHub.

Continue creating your block templates with the exercise in the next lesson.