Global Styles & theme.json

Level: , ,

Global Styles help users change the style of their site without having to edit individual blocks or pages. It also lowers the entry barrier and makes it easier for theme developers to style blocks.

In this lesson, you will learn what Global Styles are, how to create a theme.json file, and how you can benefit from Global Styles.

Estimated reading time: 14 minutes

Updated June 25, 2022, for Gutenberg version 13.5.0

What are Global Styles?

Global styles is a system and an interface created to help users change the overall style across their entire site without having to edit individual blocks or pages.

Users can select a body background color or change the line-height of all their heading blocks from one place. With style variations, the theme developer can add multiple styles that the user can choose from, for example, a dark, light, or purple version, making themes more versatile than ever before.

Styles added to individual blocks, including styles in the HTML markup of a block template, overrides Global Styles. From a theme developer perspective, Global Styles can make it easier to style blocks in the editor and front.

Both classic PHP-based themes and block themes can take advantage of global styles using theme.json. But only block themes use the new Styles interface.

The Styles interface

WordPress introduced the Styles interface as part of the Site Editor in version 5.9. You find the controls inside a separate sidebar panel in the Site Editor.

First, access the editor via Appearance > Editor in the WordPress admin:

The editor menu sits under Appearance in the sidebar menu in the WordPress admin area.

Next, open the Styles sidebar by clicking on the icon with the black and white split circle (next to the save button). In the first panel, you can access options for typography, colors, and layout for the website (padding):

From the Global Styles sidebar you can open links to Typography, color, and layout settings.
An early version of the Global Styles interface.

At the bottom of the sidebar, you can open the Blocks panel to select defaults for block types:

When you open the Blocks section of the global styles sidebar, you will find a list of links; one for each available block.  The link opens the style settings for the block type.

Who benefits from Global Styles?

Besides the users who will have more possibilities to change the look of their sites, Global Styles also benefit new theme developers.
The new controls will drastically reduce the need for custom solutions for styling, for example, a theme options panel or customizer settings. It lowers the entry barrier for new theme developers while allowing control of the styles.

How do Global Styles work?

Global Styles work with the help of a new theme settings file called theme.json. Theme developers can use JSON to define defaults for both the website and blocks.

WordPress parses the data from the JSON objects and reformats it as CSS and CSS custom properties. WordPress then loads the styles in the editors and on the front.
In classic PHP-based themes, the styles are only loaded in the editors.

In earlier versions of Gutenberg, a block needed to register support for the style properties before you could control the properties with theme.json. This is no longer the case.
You can now add default styles for all blocks, including third-party blocks from plugins.

View of the block.json file for a group block. The file includes the block information, attributes and block supports.
An example block that has registered support for alignments and gradients.

A block must register support for a feature for the control to be visible in the editors. Theme.json can not add new controls to blocks that do not register support.
– But you can use theme.json to disable existing controls.
You can read more about block supports in the block grammar lesson.

What is theme.json?

Theme.json is a new theme configuration for block settings, styles, template parts, and custom templates.

Theme.json uses JSON format. One of the reasons the Gutenberg developers selected JSON was its ease of use. If you are familiar with arrays or JavaScript Objects, you will have no problems working with theme.json.

New to JSON and want to read more about it? Then I recommend these resources:
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON
https://www.json.org/json-en.html

Since WordPress 5.9, there have been considerable improvements to the official documentation for theme.json. I strongly recommend that you bookmark the theme.json reference.

– I also want to highlight that theme.json will continue to evolve. You will be able to use new or experimental features if you activate the Gutenberg plugin.
The documentation in the block editor handbook will include information about new features. The theme developer handbook will have a beginner guide with information about what is supported in WordPress core.

How to create theme.json

You place the new theme.json configuration file in the theme’s root folder:

patterns (dir)
parts (dir)
      - footer.html
      - header.html
templates(dir)
      - 404.html
      - archive.html
      - index.html
      - page.html
      - single.html
      - search.html
functions.php
index.php
README.txt
screenshot.png
style.css
theme.json

You start the file with two curly brackets, { } and you will place all the content inside these brackets.

Then you will use a format with property names and values, encased in double quotes and separated with a colon:

{
"property-name": "value"
}

The property name can be a block name or a setting:

"core/heading": {
	"typography": {
		...
	}
}

Example theme.json file:

A view of the theme.json file from Armando. The code is truncated but displays the settings section with color, typography, spacing and layout settings.

Versioning

You need to include the version at the top of your file inside the first curly brackets.

  • Version 1 of the theme.json format is considered the earliest stable version.
  • Version 2 is used from Gutenberg 11.9 and from WordPress 5.9 (recommended).
{
	"version": 2
}

Main sections

You separate the theme.json file into two main sections: settings and styles.

  • Settings:
    • The editor configuration. Enables or disables features like custom font sizes, custom padding, and colors.
    • Defines preset values such as color palettes that generates CSS custom properties that you can use in the theme. You can define presets for both the website and per block type.
  • Styles:
    Applies styling to the website or the blocks, with or without the generated CSS custom properties.
{
        "version": 2,
	"settings": {
		"blocks": {
		}
	},
	"styles": {
                "blocks": {
                }
	}
}

Settings presets

Presets are defaults for editor controls and custom CSS properties. They are generated from the values in the settings section.
Theme.json describes every preset using a preset category. The categories are the same as the block support registered by blocks in block.json. Some categories also have subcategories.

Available categories:

  • Color
  • Typography
  • Layout
  • Spacing
  • Border
  • Custom

Color

In the example below, the preset category is color and the subcategories of color are palette, duotone, and gradients.

The official documentation sometimes presents this nesting as
settings.color.palette, settings.blocks.blockname.color.gradients

You place multiple values inside arrays and separate properties with a comma:

{
"version": 2,
"settings": {
	"color": {
		"palette": [
			{
			     "slug": "primary",
			     "color": "#D1D1E4",
			     "name": "Primary"
			},
			{
			     "slug": "secondary",
			     "color": "#E4D1D1",
			     "name": "Secondary"
			}
		],
		"gradients": [
			{
			"slug": "primary-to-secondary",
			"gradient": "linear-gradient(160deg, var(--wp--preset--color--primary), var(--wp--preset--color--secondary))",
			"name": "Primary to Secondary"
			}
		],
                "duotone": [
		         {
				"colors": [ "#1d1f35", "#6cace4" ],
				"slug": "dark-blue-and-light-blue",
				"name": "Dark blue and light blue"
			},
			{
				"colors": [ "#1d1f35", "#c7c0af" ],
				"slug": "dark-blue-and-beige",
				"name": "Dark blue and beige"
			}
		]
             }
      }
}

If you look at the gradient above, you can see that it uses the primary and secondary colors from the palette. Each preset generates a CSS custom property using this naming convention:

--wp--preset--{preset-category}--{preset-slug}

And the output from the example is:

--wp--preset--color--primary: #D1D1E4;
--wp--preset--color--secondary: #E4D1D1;

--wp--preset--gradient--primary-to-secondary: linear-gradient(160deg, var(--wp--preset--color--primary), var(--wp--preset--color--secondary));

Typography

You can add font families and font sizes under the typography category.

FontFamilies contains an array with the following keys:

  • fontFamily: A list of one or more font family names.
  • slug: The slug is used to identify the font families. It is also used in the CSS custom property.
  • name: The visible name of the font families in the editor. Optional.

FontSizes is the theme.json equivalent of add_theme_support( "editor-font-sizes" ).
The size property can use any valid CSS font size.

{
	"version": 2,
	"settings": {
		"typography": {
			"fontFamilies": [
				{
					"fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
					"slug": "system-fonts",
					"name": "System Fonts"
				},
				{
					"fontFamily": "Geneva, Tahoma, Verdana, sans-serif",
					"slug": "geneva-verdana"
				}
			],
			"fontSizes": [
				{
					"slug": "small",
					"size": "1rem",
					"name": "Small"
				},
				{
					"slug": "extra-large",
					"size": "3rem",
					"name": "Extra large"
				}
			]
		}
	}
}

Layout and content width

The layout category replaces add_theme_support( 'align-wide' ); and defines the width of the content.

  • contentSize -Default block width.
  • wideSize -Width of blocks with the wide align setting enabled.

This setting does not output CSS custom properties.

Place this code under settings:

"layout": {
	"contentSize": "840px",
	"wideSize": "1100px"
}

Custom presets

When you create a theme.json file and add custom presets, you are not limited to using properties supported by the block. In comparison to standard presets, they do not influence the block controls in the editor. A custom preset can be anything. If you want to handle all your CSS custom properties in one settings file, you can use theme.json to create CSS custom properties that you can use anywhere in your CSS.

"custom": {
	"spacing": "14px"
}

Custom preset generates a CSS custom property using this naming convention:

--wp--custom--slug

Because of this, you should not use -- in your slug or values.

The output from the example is:

--wp--custom--spacing: 14px;

Presets for blocks

With block presets, you can add settings to a specific block type. In the next example, I show you how to add a custom color palette to the heading block.
When you add a custom palette to a block, it replaces the default palette.

Create a new section called blocks inside settings:

{
    "version": 2,
    "settings": {
           "blocks": {
           }
    }
}

Add the name of the block, core/heading, inside the new blocks section:

{
    "version": 2,
    "settings": {
           "blocks": {
              "core/heading":{
              }
           }
    }
}

Any presets you create inside this section will only apply to the heading block.

"core/heading":{
       "color": {
		"palette": [
			{
				"slug": "tertiary",
				"color": "#1d1f35",
				"name": "Tertiary"
			}
		]
       }
}
Example with both color palettes together.
{
	"version": 2,
	"settings": {
		"color": {
			"palette": [
				{
					"slug": "primary",
					"color": "#ff0000",
					"name": "Primary"
				},
				{
					"slug": "secondary",
					"color": "#00b000",
					"name": "Secondary"
				}
			]
		},
		"blocks": {
			"core/heading": {
				"color": {
					"palette": [
					        {
						        "slug": "tertiary",
							"color": "#1d1f35",
							"name": "Tertiary"
						}
					]
				}
			}
		}
	}
}
	

Enable or disable features

Reminder: When a feature is enabled, the editor control is available, but only for the blocks that have registered support.

AppearanceTools -A setting that enables multiple features

In Gutenberg version 12.1, the editor team added a new setting to theme.json called appearanceTools. AppearanceTools enables the following features:

  • Border radius, color, style, and width
  • Link color
  • BlockGap, margin, and padding
  • Line height

Typography features

  • customFontSize: Let the user select a custom size value. Enabled by default, set to false to disable.
  • dropCap: Let the user add a drop cap to paragraphs. Enabled by default, set to false to disable.
  • fontWeight: Enabled by default, set to false to disable.
  • lineHeight: Opt-in, set to true to enable.
  • fontStyle: Enabled by default, set to false to disable.
  • textDecoration: Let the user add an underline or line through text. Enabled by default, set to false to disable.
  • textTransform: Let the user select uppercase, capitalized and lowercase text. Enabled by default, set to false to disable.

Example code:

"typography": {
	"lineHeight": true,
        "customFontSize": false,
        "dropCap": false
}

– It is not possible to choose which font weights that should be available in the editor.

Color features

The color options include:

  • custom: Let the user select custom colors using the color picker. Enabled by default, set to false to disable.
  • customGradient: Let the user select custom gradients using the color picker. Enabled by default, set to false to disable.
  • customDuotone: Let the user select custom highlights and shadows for the duotone. Enabled by default, set to false to disable.
  • link: Let the user select a link text color. Used for all link states. Opt-in, set to true to enable.
  • background: Let the user select background colors. Set to false to disable.
  • text: Let the user select text colors. Set to false to disable.
"color": {
	"custom": false,
	"customGradient": false,
	"customDuotone": false,
	"customDuotone": false,
        "background": false,
        "text": false,
        "link": true
}

For more color options please read the lesson about theme.json colors.

Spacing features

Enable support for custom padding and margin:

"spacing": {
        "padding": true,
	"margin": true
}

Enable custom units for the margin and padding:

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

To learn about the blockGap spacing feature, please continue to the lesson about Layout.

Borders

Enable support for borders:

"border": {
	"color": true,
	"radius": true,
	"style": true,
	"width": true
}

Styles

Objects at the top level of the styles section are styles that affect the website.
Objects inside “blocks” are styles that affect the named block type.

In the example, I use a color hex value for the background and a global styles preset for the text. I have defined the preset in the settings but truncated it for readability.

{
        "version": 2,
	"settings": { ... },
	"styles": {
		"color": {
			"background": "#FFF",
			"text": "var(--wp--preset--color--primary)"
		}
	}
}

And the CSS output is:

body {
	background-color: #FFF;
	color: var(--wp--preset--color--primary);
}

Block Styles

Block styles overrides the default styles for blocks. WordPress applies the styles to all instances of the block. For block styles, the category name is always an existing property.

You can find the available properties in the official documentation and the block reference.

In the example, I am adding the primary text color to the heading block:

{
        "version": 2,
	"settings": {...},
	"styles": {
		...,
               "blocks": {
	             "core/heading": {
			     "color": {
				      "text": "var(--wp--preset--color--primary)"
			     }
		     }
              }
	}
}

The resulting CSS output is:

h2 { color: var(--wp--preset--color--tertiary); }

Additional sections

Template part areas

With full site editing, there are three optional template part areas: header, footer, and uncategorized (general).

You can assign a template part that you have designed as a header to the header area.
This helps users select the correct template parts when they are creating or editing their website.

This section is at the base level of theme.json. The section name is templateParts, followed by the slug of the template part and the name of the area. The title is the visible name in the editor.

In the example, the template part file name is header.html, which means that header is the slug you need to use as a value for the name property:

"templateParts": [
	{
		"name": "header",
		"area": "header",
		"title": "Header"
	}
]

wp_template_part_area is a taxonomy for the wp_template_part post type.

Custom templates

A custom template is a template that you can select in the Site Editor or assign to a post or page in the block editor.

With a traditional PHP-based theme, you place the required information in the file header of the template file:

/**
 * Template Name: Grid
 *
 * Description: A Page Template that displays your posts in a grid.
 *
 * @package Aaron
 */

With full site editing, you can list templates in theme.json.
The section name is customTemplates and just like the settings, styles, and templateParts, the section is at the base level of theme.json.

The first key is the name and slug of the template. In the example, I have named the template file page-home.html, and the slug is page-home.

  • title is the template name that is visible in the editor.
  • postTypes is an array of supported post types.
"customTemplates": [
	{
		"name": "page-home",
		"title": "Page without title",
		"postTypes": [ "page", "post" ]
	}
]

-There is a suggestion to change “name” to “slug” for ease of use.

Patterns

The patterns section was added to theme.json in Gutenberg version 12.7, to make it easier to include patterns from the WordPress.org pattern directory.

It is in the root level of theme.json and uses an array of block pattern slugs:

"patterns": [ "short-text-surrounded-by-round-images", "partner-logos" ]

Visit the pattern directory and select the pattern you want to include. For example, this beautiful gallery pattern made by Mel Choyce-Dwan.
The slug of the pattern is the last part of the URL: mixed-shape-gallery, and the code for the pattern section would be:

"patterns": [ "mixed-shape-gallery" ]

Schema

WordPress contributors have created a schema to help you use theme.json.
By including the schema at the top of the file, you can validate the file, see tooltips with descriptions of the settings, and autocomplete in your code editor.
The link to the schema is:

"$schema": "https://schemas.wp.org/trunk/theme.json"

Placement:

{
        "$schema": "https://schemas.wp.org/trunk/theme.json",
        "version": 2,

– Adding the schema to the file is not required for theme.json to work, but it is incredibly helpful while you are making edits.

Official documentation for the schema

Style priority

Now you know that theme.json creates custom CSS properties and overrides default styles for blocks. I have also showed a screenshot of the interface where the user can select global styles. The user selected styles have priority over the styles created with theme.json.

  1. Styles added to an individual block in the block editor, for example, via color options (Note that some of these styles are inline, in the style attribute).
  2. Styles added via the Styles interface.
  3. Stylesheets that you enqueue: Specificity and use of !important matters! There are always ways to override styles.
  4. Styles added in the theme.json file.
  5. Default block styles from WordPress (or Gutenberg, if the plugin is active).