Theme.json

What is theme.json?

Theme.json It is a configuration file for theme styles and block settings.

The feature was added in WordPress version 5.8 and does not work with older versions of WordPress unless you activate the Gutenberg plugin.

Some of the things you can do with theme.json are:

  • Enable or disable features like drop cap, padding, margin, and custom line-height
  • Add multiple color palettes, gradients, and duotones
  • Add font sizes
  • Add default widths for content and wide content
  • Add custom CSS properties
  • Assign template parts to template part areas

When you add theme.json to your theme, the template editor is enabled.

There are important differences between what is available for theme.json in WordPress version 5.8 (version 1), WordPress 5.9 (version 2), and the Gutenberg plugin (experimental features).
This page includes information about version 2 of theme.json.

This page is a complement to the How-to guide in the block editor handbook and to the theme.json reference.

Top ↑

How to create a theme.json file

Create a new file called theme.json inside the root folder of your theme. 

Next, add a pair of curly brackets, and inside the curly brackets, include the version number:

{
    "version": 2
}

It’s important to include the version attribute; otherwise, the data will be parsed as “version 0”, which differs greatly from the expected behavior outlined here.

There are two main sections:

  • Settings, where you define your block controls and color palettes, font sizes, and more.
  • Styles, where you apply these colors and font sizes to the website and blocks.

Add the section name, place your settings between the curly brackets, and separate objects with commas:

{
    "version": 2,
    "settings": {
          "color": {},
          "typography": {}  
    }
}

You can target both the website and blocks with settings and styles:

  • Place global, site wide settings at the root level of a section
  • Place block settings inside “blocks”, followed by the block name
{
	"version": 2,
	"settings": {
		"color": { ... }, // Global settings
		"blocks": {
			"core/group": { 
				"color": { ... }, // Group block color settings
				"typography": { ... } // Group typography settings
			}
		}
	}
}

Top ↑

Preset Values

WordPress uses data from theme.json to control the editor’s block settings and create CSS custom properties. An example of this is the color palette. The values are used to provide the user with color palette options and to generate CSS properties that you can use elsewhere in theme.json or in the theme’s CSS.

This example shows a color palette with a single black color:

{
    "version": 2,
    "settings": {
        "color": {
            "palette": [
                {
                    "name": "Black",
                    "slug": "black",
                    "color": "#000000"
                }
            ]
        }
    }
}

This results in the generation of the CSS variable in the body of the website:

--wp--preset--color--black: #000000;

This example shows a color palette added only to the paragraph block with a single blue color:

{
    "version": 2,
    "settings": {
            "blocks": {
                "core/paragraph": {
                    "color": {
                        "palette": [
                            {
                                "name": "Blue",
                                "slug": "blue",
                                "color": "#0000FF"
                            }
                        ]
                    }
                }
            }
        }
    }        
}

That example will make available the following CSS variable within the paragraph block element:

--wp--preset--color--blue: #0000FF;

Top ↑

Custom Values

Values stored in the settings.custom area (or settings.blocks.BLOCKNAME.custom areas) generates CSS properties that you can use elsewhere in the theme.json file or the theme’s CSS.

{
    "version": 2,
    "settings": {
            "custom": {
                "fruit": "apple"
            },
            "blocks": {
                "core/paragraph": {
                    "custom": {
                        "fruit": "pear"
                    }
                }
            }
        }
    }        
}

The above will cause the CSS variable --wp--custom--fruit to be created with a value of “apple”. However, the value will be “pear” for the “core/paragraph” elements.

Top ↑

A theme.json can be added to any theme

Theme.json works with both classic PHP-based themes as well as block themes. Theme.json does not work with the classic editor.

If you add a theme.json file to an existing theme, you may need to adjust the theme’s CSS and remove duplicate styles for theme.json to work properly.
Additionally, the alignment mechanism for “full” and “wide” blocks works differently with a theme.json present and should be considered.

Note that the settings in theme.json replace many of the calls to add_theme_support(). The color palette in theme.json is the equivalent of add_theme_support( 'editor-color-palette', …).
When both are present, the palette from theme.json takes precedence.

Top ↑

Settings

Top ↑

Color

Each color, gradient, and duotone has three key- and value pairs:

  • slug, used in the CSS preset
  • [color, gradient, or colors]
  • name, the visible name in the editor (optional).

Top ↑

Color palette

The color value for the palette item can be any valid CSS color value such as “blue” or a hex color such as “#00FF00”.

Top ↑

Gradients

You can create gradients with any valid CSS color value and assign them to the “gradient” key. The example below uses the CSS properties generated from the palette.

Top ↑

Duotone

Duotone colors are expressed in an array assigned to the “colors” key. They must be hex or rgb color values.

{
    "version": 2,
        "settings": {
            "color": {
                "palette": [
                    {
                        "slug": "purple",
                        "color": "#D1D1E4",
                        "name": "Purple"
                    },
                    {
                        "slug": "yellow",
                        "color": "#EEEADD",
                        "name": "Yellow"
                    }
                ],
                "gradients": [
                    {
                        "slug": "purple-to-yellow",
                        "gradient": "linear-gradient(160deg, var(--wp--preset--color--purple), var(--wp--preset--color--yellow))",
                        "name": "Purple to Yellow"
                    }
                ],
                "duotone": [
                    {
                        "slug": "purple-and-yellow",					
                        "colors": [ "#D1D1E4", "#EEEADD" ],
                        "name": "Purple and yellow"
                    }
                ]
            }
        }
    }
}

Top ↑

Typography

Top ↑

Font size

Font sizes defined in theme.json supersede values assigned via the ‘editor-font-sizes’ theme support. They consist of the same three values: slug, size and name.

{
	"version": 2,
	"settings": {
		"typography": {
			"fontSizes": [
				{
					"slug": "small",
					"size": "1rem",
					"name": "Small"
				},
				{
					"slug": "medium",
					"size": "1.5rem",
					"name": "medium"
				}
			]
		}
	}
}

Top ↑

Layout

The layout setting enables wide and full-width blocks. Note that the alignment mechanism leveraged here is different than what was previously enabled via align-wide theme support.

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

Top ↑

Spacing

Enable custom margin, padding, and custom spacing units:

{
	"version": 2,
	"settings": {
		"spacing": {
			"padding": true,
			"margin": true,
			"units": [ "px", "em", "rem", "vh", "vw", "%" ]
		}
	}
}

Top ↑

Enabling and disabling settings

Within settings, you can enable or disable block controls in the editor.

The following features are enabled by default:

  • Custom colors (The color picker)
  • Custom duotone (The color picker)
  • Custom gradient (The color picker)
  • Custom font size
  • Drop cap

To disable them, you need to set the setting’s value to false.

This example disables the custom color picker for the color palette and gradients:

{
	"version": 2,
	"settings": {
		"color": {
			"custom": false,
                        "customGradient": false
                 }
         }
}

This example disables dropCap:

{
	"version": 2,
	"settings": {
		"typography": {
			"dropCap": false
                 }
         }
}

The following features are disabled by default:

  • Link color
  • Padding and margin
  • Custom line-height

To enable them, you need to set the setting’s value to true.

Example:

{
	"version": 2,
	"settings": {
		"color": {
			"link": true
                 },
                "typography": { 
                         "lineHeight": true
                }
         }
}

Or, you can enable AppearanceTools to enable these features in one single setting:

  • border: color, radius, style, width
  • color: link
  • spacing: blockGap, margin, padding
  • typography: lineHeight
{
	"version": 2,
	"settings": {
		"appearanceTools": true,
         }
}

Top ↑

Styles

Just like settings, styles that are applied to the website body are placed on the root level of the styles section.

{
    "version": 2,
    "settings": { ... },
    "styles":{
        "color":{
            "background":"var(--wp--preset--color--white)",
            "text":"var(--wp--preset--color--black)"
        },
        "typography":{
            "fontSize":"1.5rem",
            "fontFamily":"var(--wp--preset--font-family--system-fonts)",
            "lineHeight":"1.5"
        },
        "spacing":{
            "margin":{
                "top":"0px",
                "right":"0px",
                "bottom":"0px",
                "left":"0px"
            }
        }
    }
}

Styles that are applied to blocks are placed under styles.blocks.BLOCKNAME:

{
    "version": 2,
    "settings": { ... },
    "styles": {
        "blocks": {
            "core/post-title": {
                "typography": {
                    "fontSize":"var(--wp--preset--font-size--extra-large)"
                }
            },
            "core/paragraph": {
                "typography": {
                    "fontSize":"var(--wp--preset--font-size--normal)"
                }
            }
        }
    }
}

Top ↑

Theme.json elements

Blocks can have multiple HTML elements. You can use elements to style headings (H1-H6) and links inside blocks.
In this example, background color and padding are added to the read more link inside the post excerpt block:

{
    "version": 2,
    "settings": { ... },
    "styles": {
        "blocks": {
            "core/post-excerpt": {
                "elements": {
                    "link": {
                        "color": {
                            "background": "var(--wp--preset--color--light-grey)"
                        },
                        "spacing": {
                            "padding": {
                            "top": "calc(.667em + 2px)",
                            "right": "calc(1.333em + 2px)",
                            "bottom": "calc(.667em + 2px)",
                            "left": "calc(1.333em + 2px)"
                        }
                    }
                }
            }
        }
    }
}

Top ↑

Assigning template parts

You assign default template parts to template areas in the templateParts section.
Add three keys: name, the file name of the template part file without the file extension, area, the name of the template area, and title, the visible name in the editor. There are three template areas to choose from: header, footer, and uncategorized (general).

Example from Twenty Twenty-Two:

"templateParts": [
	{
		"name": "header",
		"title": "Header",
		"area": "header"
	},
	{
		"name": "header-large-dark",
		"title": "Header (Dark, large)",
		"area": "header"
	},
	{
		"name": "header-small-dark",
		"title": "Header (Dark, small)",
		"area": "header"
	},
	{
		"name": "footer",
		"title": "Footer",
		"area": "footer"
	}
]

Top ↑

Defining custom templates

In a classic theme, custom page templates are identified with a file header. In a block theme, you can list block templates in the theme.json file.
All templates that are listed in the customTemplates section of theme.json are selectable in the Site Editor. For templates to be editable in the template editor, the template’s file name needs to be prefixed with the post type (usually post- or page-).

Add two keys: name, the file name of the template part file without the file extension, title, the visible name in the editor. There is also an optional setting where you decide which post types that can use the template. The key is postTypes, followed by the name of the post type:

"customTemplates": [
    {
        "name": "page-home",
        "title": "Page without title"
    },
    {
        "name": "page-contact",
        "title": "Contact",
        "postTypes": [ "page" ]
    }
]

Top ↑

Changelog:

  • Updated 2022-02-15. Added % to spacing units, added information about templateParts and customTemplates.
  • Created 2022-01-20

Written by @pbking and @poena.