Exercise: Creating theme.json

In this short exercise, you will practice creating a theme.json file for a WordPress block theme.
You will create presets and add some basic styling to the theme.
This lesson is suitable for those who want a quick recap of the global styles lesson.

Level: Beginner, intermediate, developer

For this full site editing lesson you will need a:

  • WordPress installation with some test content and the Gutenberg plugin.
  • Block theme with at least one header and one footer template part.

If you created a theme with template parts in the previous exercise, you can continue using it for this exercise.

Or, you can download the theme from GitHub here: Part two of the lesson files.

Download the final code for the project created in this lesson.

Estimated reading time: 8 minutes

This lesson and the example files were updated on July 21, 2021.

With the help of the theme.json file, we are going to turn this:

A preview of the theme without styles, before creating theme.json. The theme has a white background, black text and purple links.

into this:

The front of the website with styles applied, after creating theme.json. The background is dark grey, and the text is white with turquoise links.

Creating the theme.json file

Open your theme files in your code editor. In the main theme folder, create a file called theme.json.
The file will have three sections: settings, styles, and templateParts.

I recommend that you add one section at the time, because one single error in the file will cause all other settings to break.

The Gutenberg developers are working on improving the error handling in theme.json.

First you will add the default settings. Default settings applies to all blocks but can be overridden on a per-block basis.

Start with the opening and closing brackets:

{
}

Inside these brackets, add the version number (1) and the settings section:

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

Color palette

Next, add the first colors to the color palette. Remember to encase the colors with brackets, and separate them with a comma. There should not be a trailing comma after the last color.

This setting is the equivalent of the editor-color-palette theme support.
The slug will be used in the generated CSS class, and the name is the visible name in the editor:

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

Add a few more colors that you can use in the design of the theme:

{
        "version":1,
	"settings": {
		"color": {
			"palette": [
				{
					"slug": "black",
					"color": "#000000",
					"name": "Black"
				},
				{
					"slug": "white",
					"color": "#FFFFFF",
					"name": "White"
				},
				{
					"slug": "dark-grey",
					"color": "#121212",
					"name": "Dark grey"
				},
				{
					"slug": "medium-grey",
					"color": "#383838",
					"name": "Medium grey"
				},
				{
					"slug": "cyan",
					"color": "#00838f",
					"name": "Cyan"
				},
				{
					"slug": "light-cyan",
					"color": "#4fb3bf",
					"name": "Light cyan"
				}
			]
		}
	}
}

After the palette, inside colors, add a gradient using the custom color presets you just created.

The presets for light cyan and white are converted into these CSS custom properties:

--wp--preset--color--light-cyan
--wp--preset--color--white

Use the CSS custom properties to define the gradients:

"gradients": [
	{
	"slug": "light-cyan-to-white",
"gradient": "linear-gradient(135deg, var(--wp--preset--color--light-cyan), var(--wp--preset--color--white))",
	"name": "Light cyan to white"
	}
]

This setting is the equivalent of the editor-gradient-presets theme support.

Typography

The typography sub-section in theme.json covers font families, sizes and line-height.

Add typography after color (the code is truncated):

{
        "version":1,
	"settings": {
		"color": { ... },
		"typography": {
		}
	}
}

Font families

August 6, 2021
Heads up: There is a known bug with font families when WordPress 5.8 and Gutenberg is used. The font family CSS is missing on the front of the website. The bug has been found and will be fixed in Gutenberg 11.3.

With this code example I am adding three sets of font families: system fonts, sans-serif and serif.
The Name property is the visible name in the editor. If name is not included, the fontFamily value will be visible instead.

To use a third party service like google fonts, you need to enqueue the files both for the editor and the front, and add the name as a value for fontFamily.

"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"
		},
		{
			"fontFamily": "Cambria, Georgia, serif",
			"slug": "cambria-georgia"
		}
       ]
}

Font sizes

This setting is the equivalent of the editor-font-sizes theme support.

  • The slug is used in the generated CSS class name.
  • The size property can be any CSS that is valid for font sizes, using for example em, rem or px units.
  • The Name property is the visible name in the editor.

Adjust the font sizes that you would like to use in your theme.

For the sake of simplicity, you can optionally copy and paste the following example from the TT1 Blocks theme:

"fontSizes": [
	{
		"slug": "extra-small",
		"size": "16px",
		"name": "Extra small"
	},
	{
		"slug": "small",
		"size": "18px",
		"name": "Small"
	},
	{
		"slug": "normal",
		"size": "20px",
		"name": "Normal"
	},
	{
		"slug": "large",
		"size": "24px",
		"name": "Large"
	},
	{
		"slug": "extra-large",
		"size": "40px",
		"name": "Extra large"
	},
	{
		"slug": "huge",
		"size": "96px",
		"name": "Huge"
	}
]

Line height

The global styles equivalent of add_theme_support( 'custom-line-height' );.
You can enable custom line heights by adding:

"customLineHeight": true

Padding & Margin

Inside settings, enable support for custom padding and margin:

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

Layout

The layout section is one of the most recent changes to global styles in WordPress. In this setting, developers define the default width of the blocks, and the width for wide blocks.

"layout": {
	"contentSize": "840px",
	"wideSize": "1100px"
}
View the complete code for the settings section
{
        "version":1,
	"settings": {
		"color": {
			"palette": [
				{
					"slug": "black",
					"color": "#000000",
					"name": "Black"
				},
				{
					"slug": "white",
					"color": "#FFFFFF",
					"name": "White"
				},
				{
					"slug": "dark-grey",
					"color": "#121212",
					"name": "Dark grey"
				},
				{
					"slug": "light-grey",
					"color": "#383838",
					"name": "Light grey"
				},
				{
					"slug": "cyan",
					"color": "#00838f",
					"name": "Cyan"
				},
				{
					"slug": "light-cyan",
					"color": "#4fb3bf",
					"name": "Light cyan"
				}
			],
			"gradients": [
				{
					"slug": "light-cyan-to-white",
					"gradient": "linear-gradient(135deg, var(--wp--preset--color--light-cyan), var(--wp--preset--color--white))",
					"name": "Light cyan to white"
				}
			]
		},
		"typography": {
                        "customLineHeight": true,
			"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"
				},
				{
					"fontFamily": "Cambria, Georgia, serif",
					"slug": "cambria-georgia"
				}
			],
			"fontSizes": [
				{
					"slug": "extra-small",
					"size": "16px",
					"name": "Extra small"
				},
				{
					"slug": "small",
					"size": "18px",
					"name": "Small"
				},
				{
					"slug": "normal",
					"size": "20px",
					"name": "Normal"
				},
				{
					"slug": "large",
					"size": "24px",
					"name": "Large"
				},
				{
					"slug": "extra-large",
					"size": "40px",
					"name": "Extra large"
				},
				{
					"slug": "huge",
					"size": "96px",
					"name": "Huge"
				}
			]
		},
                "spacing": {
	                "customPadding": true,
                        "customMargin": true,
	                "units": [ "px", "em", "rem", "vh", "vw" ]
                },
                "layout": {
	                 "contentSize": "840px",
	                 "wideSize": "1100px"
     		}
	}
}

Styling the website

Now that you have created some theme.json presets, you can use them to add styles to the website.
At the top level, below settings, add the styles section:

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

{
        "version":1,
	"settings": { ... },
	"styles": {
	}
}

Set the body background color to a pleasant dark grey using the preset
--wp--preset--color--dark-grey.
Set the text color to white:

{
        "version":1,
	"settings": { ... },
	"styles": {
		"color": {
			"background": "var(--wp--preset--color--dark-grey)",
			"text": "var(--wp--preset--color--white)",
		}
	}
}

To change the body link color, you need to use elements.
Below color, add elements, and then select which element to target, in this case, link:

{
        "version":1,
	"settings": { ... },
	"styles": {
		"color": {
			"background": "var(--wp--preset--color--dark-grey)",
			"text": "var(--wp--preset--color--white)",
		},
                "elements": {
                    "link": {}
                }
	}
}

You can add both typography settings and colors inside elements.link, but I am going to show an example of how to add a text color:

{
        "version":1,
	"settings": { ... },
	"styles": {
		"color": {
			"background": "var(--wp--preset--color--dark-grey)",
			"text": "var(--wp--preset--color--white)"
		},
                "elements": {
                    "link": {
        		"color": {
 			    "text": "var(--wp--preset--color--light-cyan)",
		        }
                    }
               }
	}
}

For the fonts I am selecting a default font size of 20px, which has the preset slug of “normal”, and the system fonts:

{
        "version":1,
	"settings": { ... },
	"styles": {
		"color": { ... },
		"typography": {
			"fontSize": "var(--wp--preset--font-size--normal)",
			"fontFamily": "var(--wp--preset--font-family--system-fonts)",
			"lineHeight": "1.7"
		}
	}
}

And the resulting CSS output is:

body {
	--wp--style--color--link: var(--wp--preset--color--light-cyan);
	background-color: var(--wp--preset--color--dark-grey);
	color: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--system-fonts);
	font-size: var(--wp--preset--font-size--normal);
	line-height: 1.7;
}

Assign content to the template part areas

Finally, add a new section called templateParts at the bottom of theme.json.
The theme that we created in the previous lesson has two template parts, header and footer.
Assign the header.html template part file to the header area, and footer.html to the footer area:

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

Preview

With the styles added, preview the theme on the front to see the result.

A screenshot of the front of the website with styles applied, displaying wide and full width columns blocks.

Download the example theme for this lesson from GitHub.