Global Styles & theme.json

Global styles is a system created to help users change the overall style of their site, without having to edit individual blocks or pages. Its purpose is also to lower the entry barrier and make 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.

Level: Beginner, intermediate, developer

Estimated reading time: 11 minutes

Updated on July 21, 2021.
An updated description of the new elements concept is being written.

July 21, 2021
This lesson has not been updated for WordPress 5.8 and Gutenberg 11.1. I hope to find the time to do this within the next few days!

I will be splitting the examples into separate pages, including one about elements.
//Carolina

What are Global Styles?

Global styles is a system created to help users change the overall style of their site, without having to edit individual blocks or pages.

Users will be able to select a body background color or change the line-height of all their headings from one place. Styles added to individual blocks will still override the global styles.

Global styles has also been created to make it easier for developers to style their blocks both in the editor and the front.

Even though it is called Global Styles, it is not only used for styles but also for enabling or disabling settings and features. A feature can be for example the drop cap.

The global styles interface is still experimental. If you are using the latest version of Gutenberg and enable a full site editing theme you can preview and test the new controls.

The controls are placed inside a separate sidebar panel in the site editor. Open the sidebar by clicking on the Aa icon.

Global styles sidebar

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 does global styles work?

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

The data from the JSON objects are parsed and reformatted as CSS and CSS variables.
The styles are then added to the editors and the front.

In earlier versions of Gutenberg, a block needed to add support for style properties before these properties could be controlled with the theme.json file. This is no longer the case. All blocks can now be styled. Block support is still used to add a user facing control in the block settings sidebar.

For those who are interested in seeing how the data is fetched, stored and parsed, see the global-styles.php file in the Gutenberg plugin.

The way CSS is loaded was improved significantly in Gutenberg version 9.6. Gutenberg now only loads the styles of the blocks that are used on a page.
If you are interested in learning about the continued work to improve the performance, see https://github.com/WordPress/gutenberg/pull/28358

The theme.json file

A file called theme.json is created and placed inside the main folder of the theme.
If you have already taken the block attributes lesson, you may recognize the format.

If you are new to JSON and want to read more about it first, I recommend these resources:
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON
https://www.json.org/json-en.html

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

Then 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": {
		...
	}
}

These may be nested in several levels, as you will see in the examples below.

Versioning

Version 1.0 of the formatting of the theme.json is considered stable and is included in 10.6.
The format used before version 1.0 will continue to work until WordPress 5.8.

At the top of your file, inside the first set of curly brackets, add the version:

{
	"version": 1
}

Main sections and sub sections

The theme.json file is separated into two main sections: settings and styles.

-There are also sections for other type of information like post templates and template parts, and we will discuss them later in this lesson.

  • 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 variables that can be used by the theme. Presets can be defined both for the website and per block type.
  • Styles:
    Applies styling to the website or the blocks, with or without the generated CSS custom properties.
{
        "version": 1,
	"settings": {
		"blocks": {
		}
	},
	"styles": {
                "blocks": {
                }
	}
}

Settings presets

Presets are described using a preset category. The categories are block properties that correspond to controls in the editor. Some have subcategories.

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

In the official documentation, this nesting is sometimes presented as
settings.color.palette, settings.blocks.blockname.color.gradients

Multiple values are placed inside arrays. You separate properties with a comma:

{
"version": 1,
"settings": {
	"color": {
		"palette": [
			{
			     "slug": "purple",
			     "color": "#D1D1E4",
			     "name": "Purple"
			},
			{
			     "slug": "red",
			     "color": "#E4D1D1",
			     "name": "Red"
			}
		],
		"gradients": [
			{
			"slug": "purple-to-red",
			"gradient": "linear-gradient(160deg, var(--wp--preset--color--purple), var(--wp--preset--color--red))",
			"name": "Purple to Red"
			}
		],
                "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 purple and red colors from the palette. Each preset generates a CSS variable using this naming convention:

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

And the output from the example is:

--wp--preset--color--purple: #D1D1E4;
--wp--preset--color--red: #E4D1D1;

--wp--preset--gradient--purple-to-red: linear-gradient(160deg, var(--wp--preset--color--purple), var(--wp--preset--color--red));

Layout and content width

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

  • contentSize -The default block width.
  • wideSize -The 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

With custom presets, you are not limited to using properties that the block supports.
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 custom 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;

Enable or disable features

Typography features

  • customLineheight: Opt-in, set to true to enable.
  • customFontSize: Let the user select a custom size value. Enabled by default, set to false to disable.
  • customFontWeight: Enabled by default, set to false to disable.
  • customFontStyle: Enabled by default, set to false to disable.
  • dropCap: Let the user add a drop cap. Enabled by default, set to false to disable.

Example code:

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

Color

  • 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.
  • link: Let the user select link text color. Used for all link states. Opt-in, set to true to enable.
"color": {
	"custom": false,
	"customGradient": false,
        "link": true
}

Padding & Margin

Enable support for custom padding and margin:

"spacing": {
        "customPadding": true,
	"customMargin": true
}

Enable custom units for the margin and padding:

"spacing": {
	"customPadding": true,
	"customMargin": true,
        "units": [ "px", "em", "rem", "vh", "vw" ]
}

Border

Enable support for borders:

"border": {
	"customColor": true,
	"customRadius": true,
	"customStyle": true,
	"customWidth": true
}

Presets for blocks

In the same way that you can create a default color palette, you can also create a palette specifically for a block. The block palette is used instead of the default palette.

These code examples are truncated but illustrate how you can create block presets:

Create a new section called blocks under settings:

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

Add the name of the block inside the new blocks section. In this example, I am using the heading block:

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

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

"core/heading":{
       "color": {
		"palette": [
			{
				"slug": "dark-blue",
				"color": "#1d1f35",
				"name": "Dark blue"
			},
			{
				"slug": "light-blue",
				"color": "#6cace4",
				"name": "Light blue"
			},
			{
				"slug": "light-grey",
				"color": "#fafafa",
				"name": "Light grey"
			}
		]
       }
}

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.


In the example, I am using a color hex value for the background, and a global styles preset for the text.

The preset is defined in the settings, but the code in the example is truncated.

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

And the CSS output is:

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

Block Styles

Block type styles are default styles for blocks. The styles are applied to all instances of a block type.

Block type styles overrides global styles.
Additional styles added by the theme can be used to override styles for individual blocks.
The styles can be overwritten per block, by selecting the block in the editor and adjusting the options in the block sidebar.

For block styles, the category name is always an existing property. A block must first have support for a property before that property can be changed.

The available properties can be found in the official documentation.

In the example, the red text color is applied to the heading block:

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

The resulting CSS output is:

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

Additional sections

Template part areas

In the site editor, there are two optional template part areas: header and footer.
A template part that has been designed as a header can be assigned to the header area.
This helps users select the correct templates 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 name and slug of the template part and the name of the area:

"templateParts": [
	{
		"name": "header",
		"area": "header"
	},
	{
		"name": "footer",
		"area": "footer"
	}
]

wp_template_part_area is a taxonomy for the wp_template_part post type.

More template part areas are likely to be added later.

Custom templates

A custom template in this scenario is a template that can be selected in the block editor in the Template section.

In a traditional PHP-based theme, the required information would be placed in the file header of the template file. With full site editing, templates are added to theme.json at the base level.

The section name is customTemplates, and the first key is the name and slug of the template.
In the example, the block template file is called page-home.html.

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

Global Style JSON examples

These examples describe the nesting of the different properties that are needed for the global styles to work.

Creating presets

Colors

{
        "version": 1
	"settings": {
		"color": {
			"palette": [
				{
					"slug": "purple",
					"color": "#D1D1E4",
					"name": "Purple"
				},
				{
					"slug": "red",
					"color": "#E4D1D1",
					"name": "Red"
				}
			],
			"gradients": [
				{
					"slug": "purple-to-red",
					"gradient": "linear-gradient(160deg, var(--wp--preset--color--purple), var(--wp--preset--color--red))",
						"name": "Purple to Red"
				},
				{
					"slug": "red-to-purple",
					"gradient": "linear-gradient(160deg, var(--wp--preset--color--red), var(--wp--preset--color--purple))",
					"name": "Red to Purple"
				}
			]
		}
	}
}

Typography

Example from TT1 Blocks and Q, including fontSizes and fontFamilies:

{
        "version": 1,     
	"settings": {
		"typography": {
			"fontSizes": [
				{
				"slug": "gigantic",
				"size": "144px",
				"name": "Gigantic"
				}
			],
			"fontFamilies": [
				{
				"fontFamily": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
				"slug": "system-font",
				"name": "System Font"
				}
			]
		}
	}
}

Applying color properties

The following color properties are available: Background, text, and gradient. You can not use a solid background and a gradient at the same time.

{
        "version":1,
	"settings": {...},
	"styles": {
		"color": {
			"background": "#FFF",
			"text": "var(--wp--preset--color--purple)",
		}
                "blocks": {
		    "core/group": {
			"color": {
				"text": "var(--wp--preset--color--purple)",
				"gradient": "var(--wp--preset--gradient--purple-to-red)",
			}
		   }
              }
	}
}

Applying typography properties

The following properties are available: font family, font size, font style, font weight, line height, text decoration, text transform.

The font size preset used in the example is created by the default font sizes in Gutenberg.

{
        "version":1,
	"settings": {...},
	"styles": {
		"typography": {
			"fontSize": "var(--wp--preset--font-size--normal)"
		},
		"blocks": {
		     "core/heading": {
			     "typography": {
				    "fontSize": "var(--wp--preset--font-size--huge)"
			     }
		     }
              }
	}
}

CSS output:

body {
	font-size: var(--wp--preset--font-size--normal);
}

h2 {
	font-size: var(--wp--preset--font-size--huge);
}