Updates for Settings, Styles, and theme.json

Changes in v2 of theme.jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML.

WordPress 5.9 is evolving the theme.json v1 introduced in WordPress 5.8 to a v2. The existing v1 theme.json files will still work as expected, and they’ll be transformed at runtime to the v2 format by WordPress.

Please, refer to the live specification document for a detailed description of the theme.json file capabilities.

Changes per section


It’s now 2 instead of 1.

You don’t need to update the v1 file for it to work, as it’ll be transformed into v2 at runtime for you. However, if you want to update a v1 file, keep in mind that you have to update the version value and potentially change the names of some keys. See below for a full set of changes.

For example, one of the changes from v1 to v2 is that the customLineHeight key has been renamed to lineHeight. Besides changing from version 1 to 2, you also need to rename the old customLineHeight name, as it’s an invalidinvalid A resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. key for the v2 file and will be ignored.


The following section documents the changes done to settings in v2:

  • appearanceTools: new key; see section below for a detailed description.
  • border:
    • customRadius has been renamed to radius.
    • colorstyle, and width keys have been added; they control the visibility of the corresponding UIUI User interface controls. false by default.
  • color:
    • text and background keys have been added. They control the visibility of the corresponding controls. true by default.
    • defaultGradients and defaultPalette keys have been added to control whether the color palette UI control should show the default colors (gradients and solids, respectively) in addition to the theme colors. true by default.
  • spacing:
    • customMargin and customPadding have been renamed to margin and padding, respectively.
    • blockGap is a new key, see section below for a detailed description.
  • typography:
    • customLineHeight has been renamed to lineHeight.
    • fontStylefontWeightletterSpacingtextDecoration, and textTransform keys have been added. They control the visibility of the corresponding UI controls. true by default.
    • fontFamilies preset has been added. Themes can now provide a list of fonts to be displayed to the user in the blocks that support the font family style. WordPress doesn’t provide any font family by default.
    • The fontSizes preset has been updated. The Normal and Huge sizes (with normal and huge slugs) have been removed from the list, and Extra Large (x-large slug) has been added. While the UI controls will no longer show the Normal and Huge values, their CSSCSS Cascading Style Sheets. classes and CSS Custom Properties are still enqueued to make sure content that uses them still works as expected.


The following section documents the changes done to styles in v2:

  • bordercolorstyle, and width styles are now allowed.
  • filter: new section to allow themes to attach filters to styles. So far, it only includes the duotone filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output..
  • spacing: added a new style property, blockGap; see section below for a detailed description.
  • typographyfontFamilyfontStylefontWeightletterSpacingtextDecoration, and textTransform styles are now allowed.

Custom templates

The customTemplates field has been introduced in version 2. It allows themes to declare their custom templates that should be present in the templates folder.

For example, for a custom template named my-custom-template.html, the theme.json can declare what post types can use it and what’s the title to show the user:

  • name: mandatory.
  • title: mandatory, translatable.
  • postTypes: optional, only applies to the page by default.

Example (theme.json):

  "version": 2,
  "customTemplates": [
      "name": "my-custom-template",
      "title": "The template title",
      "postTypes": [

Template parts

The templateParts field has been introduced in version 2. It allows themes to list the template parts present in the partsfolder.

For example, for a template part named my-template-part.html, the theme.json can declare the area term for the template part entity responsible for rendering the corresponding blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. variation (HeaderHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. block, Footer block, etc.) in the editor. Defining this area term in the theme.json will allow the setting to persist across all uses of that template part entity instead of a block attribute that would only affect one block. Defining area as a block attribute is not recommended as this is only used ‘behind the scenes’ to bridge the gap between placeholder flows and entity creation.

Currently, block variations exist for “header” and “footer” values of the area term. Any other values and template parts not defined in the json will default to the general template part block. Variations will be denoted by specific icons within the editor’s interface, will default to the corresponding semantic HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. element for the wrapper (this can also be overridden by the tagName attribute set on the template part block), and will contextualize the template part allowing more custom flows in future editor improvements.

  • name: mandatory.
  • title: optional, translatable.
  • area: optional, will be set to uncategorized by default and trigger no block variation.

Example (theme.json):

  "version": 2,
  "templateParts": [
      "name": "my-template-part",
      "title": "Header",
      "area": "header"

Appearance tools

The new setting appearanceTools serves to opt-in a number of other settings that are disabled by default, serving themes to quickly enable every setting available.

In v2, setting appearanceTools true opts-in to the following settings that are false by default:

  • border: color, radius, style, width
  • color: link
  • spacing: blockGap, margin, padding
  • typography: lineHeight


The blockGap adjusts the vertical margin, or gap, between blocks. It is also used for the gap between inner blocks in rows, buttons, and social icons. In the editor, the control for the blockGap is called Block spacing, located in the Dimensions panel.

By default the block gap support is disabled for all themes, but you can enable it in your theme.json with two different ways:

  • Set its value to false to enable the block gap styles support but keep the per block control hidden in the inspector controls of blocks.
  • Set its value to true to enable the block gap styles support and allow users to tweak the block gap per block (buttons, rows groups, social icons).

Example (theme.json):

	"version": 2,
	"settings": {
		"spacing": {
			"blockGap": true,
	"styles": {
		"spacing": {
			"blockGap": "1.5rem"

Changes to the global stylesheet

Default font sizes, colors, and gradients

The CSS for some of the presets defined by WordPress (font sizes, colors, and gradients) was loaded twice for most themes: in the block-library stylesheet plus in the global stylesheet. Additionally, there were slight differences in the CSS in both places.

We’ve consolidated the CSS of presets into the global stylesheet, that is now loaded for all themes. Each preset value generates a single CSS Custom Property and a class, as in:

/* CSS Custom Properties for the preset values */
body {
  --wp--preset--color--pale-pink: #f78da7;
  --wp--preset--font-size--large: 36px;
  /* etc. */

/* CSS classes for the preset values */
.has-<PRESET_SLUG>-<PRESET_TYPE> { ... }
.has-pale-pink-color { color: var(--wp--preset--color--pale-pink) !important; } 
.has-large-font-size { font-size: var(--wp--preset--font-size--large) !important; }

For themes to override the default values they can use the theme.json and provide the same slug. Themes that do not use a theme.json can still override the default values by enqueuing some CSS that sets the corresponding CSS Custom Property.

Example (sets a new value for the default large font size):

body {
 --wp--preset--font-size--large: <NEW_VALUE>;

In v1, when a user selected a link color for a specific block we attached a class to that block in the form of .wp-element-<ID> and then enqueued the following style:

.wp-element-<ID> a { color: <USER_COLOR_VALUE> !important; }

While this preserved user preferences at all times, the specificity was too strong and conflicted with some blocks with legit uses of an HTML element that shouldn’t be considered links. To address this issue, we removed the !important and updated the corresponding blocks to style the a elements with a specificity higher than the user link color, which now is:

.wp-element-<ID> a { color: <USER_COLOR_VALUE>; }

As a result of this change, it’s now the block author and theme author’s responsibility to make sure the user choices are respected at all times and that the link color provided by the user (specificity 011) is not overridden.

Fix for CSS Custom Property names that contain numbers

In 5.9 we fixed a bug by which the frontend and the editors would render different CSS Custom Properties. Take this example:

    "settings": {
        "color": {
            "palette": [
                    "slug": "white2black",
                    "color": "value",
                    "name": "White to Black"
        "custom": {
            "white2black": "value"

The expected result is that the engine generates the following properties (note how white2black is converted into white-2-black):

body {
  --wp--preset--color--white-2-black: "value";
  --wp--custom--white-2-black: "value";

In 5.8 the code generated for the frontend had a bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. by which it wouldn’t explode the numbers.

Props to @oandregal for writing this dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase., and @mkaz for reviewing.


  • March 10th, 2022: Fix for CSS Custom Property names that contain numbers section added and the example for a default large font size was updated to use body instead of root.

#5-9, #dev-notes