In this article, you’ll examine WordPress theme types and learn how to add block theme features to a classic theme, blending the best of both to create a powerful and flexible hybrid theme.
Table of Contents
Theme types
There are two primary theme types: classic themes and block themes.
An overview of block themes
In January 2022, WordPress 5.9 was released, and with it came the Site Editor. This new functionality allowed developers to create themes entirely from blocks while also allowing users more control over various areas of their sites, such as the header and footer, without having to write a single line of code.
A new method to apply styles globally across the site was also introduced, managed through a theme.json
file. Block themes simplify the creation of templates by leveraging a visual, block-based approach, allowing for the design of complex layouts directly in the editor. These features empower non-developers to make site-wide changes quickly and intuitively, while giving developers the flexibility to implement advanced functionality and create highly customizable themes.
An overview of classic themes
Classic themes are traditional PHP, HTML, CSS, and JavaScript based themes that date back nearly two decades to 2005, when WordPress 1.5 first introduced the theme system. They rely primarily on PHP to provide advanced functionality, which makes them a great option for developers who need to create themes with highly customized logic and integrations. Unfortunately, this dependency makes them far less accessible to non-developers as even the smallest of changes often require direct editing to the template files. While classic themes support the block editor, they do not support the Site Editor, which requires all parts of its templates to be block markup.
Key differences
Both theme types have several differences and understanding them is important to help you choose the right theme type for your project. Despite their differences, they also share a lot of functionality that you can gradually adopt over time.
The main differences between the theme types are:
- Site editor: Block themes are designed for the Site Editor which gives users more control over the look and feel of their templates, a feature that classic themes do not support.
- Templates: Classic themes leverage PHP files, allowing for highly customized templates through code. Block themes require HTML files made up of block-based markup and can be easily created right in the editor.
- Global styles: Classic themes have limited support for a
theme.json
file that can be expanded as more block theme features become available in classic themes.
Despite all the differences in functionality and how users work with each, one key difference makes a classic theme a block theme: the inclusion of a /templates/index.html
file. When this file is in place, WordPress will view it as a block theme.
Hybrid themes
Somewhere between a classic theme and a block theme, there’s a third approach that doesn’t get as much attention but is gaining more support with each WordPress release. That is the concept of a hybrid theme, one rooted in the traditional approach of a classic theme but able to leverage most of the modern features of a block theme.
Since WordPress 5.9, more and more block theme features have been made available to use in classic themes, allowing developers to gradually adopt these new features and use a mix of PHP or HTML files without making the full leap into a block theme. This is what is referred to as a hybrid theme, and throughout the rest of this article, each feature will be explored in detail.
Getting setup
To make things easier to follow along, you can clone an accompanying GitHub repository that uses underscores as a starting point. The repository contains a few new files that allow you to quickly test out hybrid theme functionality.
functions-hybrid.php
/assets/js/hybrid-theme.js
/assets/css/hybrid-theme.css
The functions-hybrid.php
file includes the two block asset enqueues that load the necessary CSS and JS files. If you are using your own theme while following along, here are the enqueues found in the example repository.
// Enqueue script into block editor
function hybrid_theme_enqueue_scripts() {
wp_enqueue_script(
'hybrid-theme-scripts',
get_template_directory_uri() . '/assets/js/hybrid-theme.js',
array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
null,
true
);
}
add_action( 'enqueue_block_editor_assets', 'hybrid_theme_enqueue_scripts' );
// Enqueue styles in block editor and front end
function hybrid_theme_enqueue_styles() {
wp_enqueue_style(
'hybrid-theme-styles',
get_template_directory_uri() . '/assets/css/hybrid-theme.css',
array(),
filemtime( get_template_directory() . '/assets/css/hybrid-theme.css' )
);
add_editor_style( 'assets/css/hybrid-theme.css' );
}
add_action( 'enqueue_block_assets', 'hybrid_theme_enqueue_styles' );
Now that you’re ready, let’s explore the block features that can be used in a classic theme and how to set them up.
If you’d like to skip ahead and see the theme with examples the repository has a branch that contains a version of the theme with most of the following examples added.
Global styles
The Global Styles and Settings API was introduced in WordPress 5.8, and developers could start controlling settings, tools, and styles in their themes through a theme.json file. Initially this feature only had partial support for classic themes, but over time, the support has expanded with each new release.
To leverage this feature, simply create a theme.json
file at the root of your theme. Here’s an example to get you started.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"layout": {
"contentSize": "768px",
"wideSize": "1024px"
},
"color": {
"palette": [
{
"slug": "primary",
"color": "#DE7D0D",
"name": "Primary"
},
{
"slug": "secondary",
"color": "#7C0DDE",
"name": "Secondary"
}
]
},
"typography": {
"fontFamilies": [
{
"slug": "default",
"name": "Default",
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif"
}
]
}
}
}
In this example, you are adding layout sizes, a basic color palette and setting the default font. There are plenty of resources out there, so I won’t go into detail on what you can and can’t do with a theme.json file, but if you want to explore that more I’d encourage you to check out the resources available in the Theme Handbook.
Block theme supports
There are several theme supports you can add to a classic theme to include both block theme features, and block functionality. Read more about theme supports in the WordPress Developer Resources.
responsive-embeds
– adds support for responsive embedseditor-styles
– adds support for loading a stylesheet in the block editordisable-custom-colors
– disables the color picker for blocksdisable-custom-font-sizes
– disables the custom font size for typography
The following theme supports will not work when a theme.json
file is in place (because they can be done in your theme.json
file, more about this below).
align-wide
– adds support for full and wide alignments in the editorcustom-line-height
– adds typography option to customize line heightcustom-spacing
– adds support for custom padding on blockscustom-units
– adds support for custom measurementseditor-color-palette
– adds support for creating custom color paletteseditor-gradient-presets
– adds support for creating custom gradient presetseditor-font-sizes
– adds support for creating custom font sizes for typography
function hybrid_add_theme_supports() {
add_theme_support( 'responsive-embeds' );
add_theme_support( 'disable-custom-colors' );
add_theme_support( 'disable-custom-gradients' );
add_theme_support( 'disable-custom-font-sizes' );
// Cannot use alongside a theme.json file
add_theme_support( 'align-wide' );
add_theme_support( 'custom-line-height' );
add_theme_support( 'custom-spacing' );
add_theme_support( 'custom-units', array( 'rem', 'em', 'px', 'vw', 'vh' ) );
add_theme_support(
'editor-color-palette',
array(
array(
'name' => __( 'Dusty Blue', 'hybrid-theme' ),
'slug' => 'dusty-blue',
'color' => '#367cb3',
),
array(
'name' => __( 'Faded Brown', 'hybrid-theme' ),
'slug' => 'faded-brown',
'color' => '#7a6a53',
),
)
);
add_theme_support(
'editor-gradient-presets',
array(
array(
'name' => __( 'Dusty to Faded', 'hybrid-theme' ),
'gradient' => 'linear-gradient(135deg, #367cb3 0%, #7a6a53 100%)',
'slug' => 'dusty-to-faded',
),
)
);
add_theme_support(
'editor-font-sizes',
array(
array(
'name' => 'Small',
'slug' => 'small',
'size' => 12
),
array(
'name' => 'Medium',
'slug' => 'medium',
'size' => 18
),
)
);
}
add_action( 'after_setup_theme','hybrid_add_theme_supports' );
Theme supports in theme.json
There’s a much easier and more efficient way to add these theme supports. In fact, you already set up a couple of them in earlier sections of this article when you created a theme.json
file. The example below adds support for everything listed above except for the responsive-embeds
support.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"layout": {
"contentSize": "1024px",
"wideSize": "1280px", // align-wide
},
"typography": {
"customFontSize": false, // disable-custom-font-sizes
"lineHeight": true, // custom-line-height
"defaultFontSizes": false,
// editor-font-sizes
"fontSizes": [
{
"name": "Regular",
"slug": "regular",
"size": "16px"
},
{
"name": "Very Big",
"slug": "very-big",
"size": "36px"
}
]
},
"color": {
"custom": false, // disable-custom-colors
"customGradient": false, // disable-custom-gradients
// editor-color-palette
"palette": [
{
"name": "Primary",
"slug": "primary",
"color": "#DE7D0D"
},
{
"name": "Secondary",
"slug": "secondary",
"color": "#7C0DDE"
},
{
"name": "Dusty Blue",
"slug": "dusty-blue",
"color": "#367cb3"
},
{
"name": "Faded Brown",
"slug": "faded-brown",
"color": "#7a6a53"
}
],
// editor-gradient-presets
"gradients": [
{
"name": "Dusty to Faded",
"slug": "dusty-to-faded",
"gradient": "linear-gradient(135deg, #367cb3 0%, #7a6a53 100%)"
}
]
},
"spacing": {
"units": [ "px", "em", "rem", "%" ] // custom-units
},
// custom-spacing (done on a per block basis)
"blocks": {
"core/columns": {
"spacing": {
"padding": true,
"margin": true
}
}
}
}
}
Block variations
The Block Variations API was introduced in WordPress 5.4 and provides developers with an easy way to create variations of existing blocks with unique starting attributes. There are a couple of steps to adding a block variation in a classic theme, but they are simple and straightforward.
Add a block variation by pasting the code below into the /js/hybrid-theme.js
. In this example, you are creating a variation on the Paragraph block called Intro Paragraph that sets new defaults for the font size, sets the drop cap to true, and uses a unique placeholder.
wp.blocks.registerBlockVariation('core/paragraph', {
name: 'intro-paragraph',
title: 'Intro Paragraph',
description: 'A paragraph with large text and a drop cap.',
attributes: {
fontSize: 'medium',
dropCap: true,
placeholder: 'Write an introduction.',
},
});
Add the new Intro Paragraph
block variation to a page and you should see something that looks like this screenshot.