Gutenberg 9.1: New JSON structure for FSE theme.json files

Following up from the post about the Gutenberg 9.1 release, there were a few changes that theme-authors experimenting with Full-Site-Editing (FSEFSE Short for Full Site Editing, a project for the Gutenberg plugin and the editor where a full page layout is created using only blocks. for short) themes should be aware of.

GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ 9.1 changed the structure of the theme.json files. This is a breaking change and previous Full Site Editing themes will need to make changes to these configuration files.

An example of how a theme.json file would look now can be seen below. Please note: For the time this file will have to be called experimental-theme.json since full-site editing is still experimental:

{
	"global": {
		"settings": {
			"custom": {
				"typo": {
					"rootSize": 16,
					"scale": 1.333
				}
			},
			"color": {
				"palette": [
					{
						"slug": "light",
						"color": "#f5f7f9"
					},
					{
						"slug": "dark",
						"color": "#000"
					}
				],
				"custom": false
			},
			"typography": {
				"fontSizes": [
					{
						"slug": "small",
						"size": "calc(var(--wp--preset--font-size--normal) / var(--wp--custom--typo--scale))"
					},
					{
						"slug": "normal",
						"size": "calc(var(--wp--custom--typo--root-size) * 1px)"
					},
					{
						"slug": "medium",
						"size": "calc(var(--wp--preset--font-size--normal) * var(--wp--custom--typo--scale))"
					},
					{
						"slug": "large",
						"size": "calc(var(--wp--preset--font-size--medium) * var(--wp--custom--typo--scale))"
					},
					{
						"slug": "huge",
						"size": "calc(var(--wp--preset--font-size--large) * var(--wp--custom--typo--scale))"
					}
				],
				"customFontSize": false,
				"customLineHeight": true
			}
		},
		"styles": {
			"color": {
				"background": "var(--wp--preset--color--light)",
				"text": "var(--wp--preset--color--dark)",
				"link": "var(--wp--preset--color--dark)"
			}
		}
	},
	"core/paragraph": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--normal)",
				"lineHeight": "1.55"
			}
		}
	},
	"core/heading/h1": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--huge)",
				"lineHeight": "1.4"
			}
		}
	},
	"core/heading/h2": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--large)",
				"lineHeight": "1.4"
			}
		}
	},
	"core/heading/h3": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--medium)",
				"lineHeight": "1.55"
			}
		}
	},
	"core/heading/h4": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--normal)",
				"lineHeight": "1.55"
			}
		}
	},
	"core/heading/h5": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--small)",
				"lineHeight": "1.8"
			}
		}
	},
	"core/heading/h6": {
		"styles": {
			"typography": {
				"fontSize": "var(--wp--preset--font-size--small)",
				"lineHeight": "1.8"
			}
		}
	}
}

The above configuration does the following:

  • Sets custom CSSCSS CSS is an acronym for cascading style sheets. This is what controls the design or look and feel of a site. variables for root font-size and a typography scale we are going to use.
  • Defines a color palette – in this case just 2 colors.
  • Builds the font-sizes using the typography scale we defined as custom properties. Though not required, in this example we show you how to implement a consistent typography scale with sizes for all headers. You can control the scale simply by changing the scale parameter in your 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.. To experiment with typography scales you can check out type-scale.com.
  • Adds defaults to 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. styles for paragraph and headers.

presets and features merged to settings

In previous versions the JSON file required a structure like this:

{
    "global": {
        "presets": {....},
        "features": {....},
        "styles": {....}
    }
}

In this latest release, presets and features were merged to settings:

{
    "global": {
        "settings": {....},
        "styles": {....}
    }
}

Custom CSS Variables

The custom section is new and allows themes to define any custom property they want. The names for custom CSS variables defined in the custom section are built with this convention:

--wp--custom--{$group}--{$property}

The group in the custom properties defined in the JSON example above is typo. It’s worth noting that while properties should be written in camelCase inside the JSON file (for example rootSize), when the css-variables are built these get converted to kebab-case (for example root-size).

With the above in mind, this:

{
    "global": {
        "settings": {
            "custom": {
                "typo": {
                    "rootSize": 16,
                    "scale": 1.333
                }
            }
        }
    }
}

will add the following CSS:

:root {
  --wp--custom--typo--root-size: 16;
  --wp--custom--typo--scale: 1.333;
}

Change in key/value pairs

Previous versions of the JSON files were using the value key to define values. For example to define a color we had to add this in our file:

{
    "slug": "light",
    "value: "#f5f7f9"
}

Now this would need to be written like this:

{
    "slug": "light",
    "color: "#f5f7f9"
}

Similarly, font-sizes will need to use size instead of value.

Thanks to @kafleg and @poena for reviewing this post