Introducing theme.json in WordPress 5.8

WordPress 5.8 comes with a new mechanism to configure the editor that enables a finer-grained control and introduces the first step in managing styles for future WordPress releases.

Controlling settings globally and per 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.

The introduction of blocks has increased the number of settings agencies and developers may need control over. Having a central point of configuration aims to provide a more consistent and complete experience.

By creating a theme.json file in the theme’s top-level directory, themes can configure the existing editor settings (the font sizes preset, whether custom colors are enabled, etc.) as well as the new ones as they are introduced (the duotone preset, whether margin and padding controls are enabled, etc.).

This new mechanism aims to take over and consolidate all the various add_theme_support calls that were previously required for controlling the editor.

The example below shows how to disable custom colors for all blocks:

{
    "version": 1,
    "settings": {
        "color": {
            "custom": false
        }
    }
}

The addition of the theme.json file also provides a way for theme authors to control these settings on a per-block basis ― something that wasn’t possible before. The example below shows how to disable custom colors for all blocks but enable them for the paragraph block:

{
    "version": 1,
    "settings": {
        "color": {
            "custom": false
        },
        "blocks": {
            "core/paragraph": {
                "color": {
                    "custom": true
                }
            }
        }
    }
}

Top-level settings will apply to all blocks that support the relevant setting. However, block-level settings can also override the top-level settings for a specific block. Blocks are addressed by their block name and settings can be added for coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. as well as third-party blocks.

Note: to retain backward compatibility, the existing add_theme_support declarations from the theme are retrofitted in the proper categories for the top-level section. For example, if a theme uses add_theme_support('disable-custom-colors'), the result will be the same as setting settings.color.custom to false. If a setting is declared in theme.json that setting will take precedence over the values declared via add_theme_support.

See the specification document for a complete list of features and backcompatibility with add_theme_support.

Blocks can access theme settings with useSetting

Core blocks have been updated to respect the new settings coming from a theme via theme.json. For example, if a block supports a UIUI User interface margin control but the theme has disabled margin across the board, the UI control will not be displayed in the editor.

Third-party blocks can also tap into this mechanism by using the useSetting ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. hook in its edit function:

import { useSetting } from '@wordpress/block-editor';
// Somewhere in the block's edit function.

const isEnabled = useSetting( 'spacing.margin' );

if ( ! isEnabled ) {
    return null;
} else {
    return <ToggleControl ... />
}

See the API docs for useSetting.

CSSCSS Cascading Style Sheets. classes for presets are automatically created and enqueued

Previously, themes had to declare presets for the editor and also enqueue the corresponding classes separately.

In the functions.php file, they’d do:

add_theme_support(
  'editor-color-palette',
  array(  /* define color presets, including translations */
) );

And then, in the style.css:

.has-<value>-color { /* ... */ }
.has-<value>-background-color { /* ... */ }
/* etc */

By using a theme.json, the theme only has to declare their presets. The engine will set up the translations and will take care of creating and enqueuing the corresponding styles to both the editor and the front-end:

{
    "version": 1,
    "settings": {
        "color": {
            "palette": [
                {
                    "name": "Color name",
                    "slug": "color-slug",
                    "color": "<color-value>"
                },
                {
                    "name": "...",
                    "slug": "...",
                    "color": "..."
                }
            ]
        }
    }
}

See the specification document for a list of classes generated by preset.

CSS Custom Properties

By phasing out IE11 support, many CSS features become available. One of these now available features is CSS Custom Properties. When a theme adds presets via theme.json, the engine will enqueue both classes and CSS Custom Properties for them.

The example below:

{
    "version": 1,
    "settings": {
        "color": {
            "palette": [
                {
                    "name": "Black",
                    "slug": "black",
                    "color": "#000000"
                },
                {
                    "name": "White",
                    "slug": "white",
                    "color": "#ffffff"
                }
            ]
        }
    }
}

will create this output in CSS:

/* One CSS Custom Property per preset value. */
body {
  --wp--preset--color--black: #000000;
  --wp--preset--color--white: #ffffff;
}

/* The corresponding classes for each preset value. */

.has-black-color { color: var(--wp--preset--color--black) !important; }
.has-black-background-color { background-color: var(--wp--preset--color--black) !important;  }

.has-white-color { color: var(--wp--preset--color--white) !important; }
.has-white-background-color { background-color: var(--wp--preset--color--white) !important;  }

See the specification document for more examples, how to add and use custom properties unrelated to presets, etc.

Managed styles for improved coordination

One of the struggles theme authors face is the conflicts that appear in an environment with core, theme, and user styles as well as the wide design area that comes with multiple blocks that can be combined indefinitely.

The theme.json file absorbs most of the common use cases for styling blocks with the goal of reducing the amount of CSS shipped to the browser, mitigating specificity wars, and providing current style info in the UI controls for users. This is the first step in having a mechanism that consolidates all the three origins of styles (core, theme, user) and that will become more important once users can provide global styles in later phases of the project.

In the example below, a theme provides styles for the top-level and a couple of blocks:

{
    "version": 1,
    "styles": {
        "color": {
            "text": "var(--wp--preset--color--primary)"
        },
        "blocks": {
            "core/paragraph": {
                "color": {
                    "text": "var(--wp--preset--color--secondary)"
                }
            },
            "core/group": {
                "color": {
                    "text": "var(--wp--preset--color--tertiary)"
                }
            }
        }
    }
}

It results in the following CSS output:

/* Top-level styles resolve to the body selector. */
body {
  color: var(--wp--preset--color--primary);
}

/* Block styles resolve to the block selector. */
p {
  color: var(--wp--preset--color--secondary);
}
.wp-block-group {
  color: var(--wp--preset--color-tertiary);
}

Any block, both core and third-party, can be targeted by its name.

See the specification document for a complete list of supported styles.

Access to other features

There are some features that are enabled or disabled when a theme has support for a theme.json file:

  • The template editor is enabled.
  • The default layout and margin styles for themes are not enqueued and the new layout options are enabled instead (see related dev note for layout).
  • The inner div for the group block (wp-block-group__inner-container) is removed.
  • The default font-family styles for the editor are not enqueued.

#5-8 #dev-notes #gutenberg