theme.json Generator

Build a block theme's theme.json: palette and font size presets, layout widths, spacing units and the style defaults, with the preset slugs checked.

Live output

Enable JavaScript to customise; default output below.

Format version

Version 3 needs WordPress 6.6 or newer. Version 2 works from 5.9.

Live preview theme.json
{
	"$schema": "https://schemas.wp.org/trunk/theme.json",
	"version": 3,
	"settings": {
		"appearanceTools": true,
		"color": {
			"custom": false,
			"customGradient": false,
			"defaultPalette": false,
			"palette": [
				{
					"color": "#FFFFFF",
					"name": "Base",
					"slug": "base"
				},
				{
					"color": "#111111",
					"name": "Contrast",
					"slug": "contrast"
				},
				{
					"color": "#1E56EC",
					"name": "Accent",
					"slug": "accent"
				}
			]
		},
		"layout": {
			"contentSize": "645px",
			"wideSize": "1340px"
		},
		"spacing": {
			"blockGap": true,
			"margin": true,
			"padding": true,
			"units": [
				"px",
				"rem",
				"vh",
				"vw",
				"%"
			]
		},
		"typography": {
			"customFontSize": false,
			"defaultFontSizes": false,
			"fluid": true,
			"fontSizes": [
				{
					"name": "Small",
					"size": "0.875rem",
					"slug": "small"
				},
				{
					"name": "Medium",
					"size": "1rem",
					"slug": "medium"
				},
				{
					"name": "Large",
					"size": "1.5rem",
					"slug": "large"
				},
				{
					"name": "X-Large",
					"size": "2.25rem",
					"slug": "x-large"
				}
			],
			"lineHeight": true
		},
		"useRootPaddingAwareAlignments": true
	},
	"styles": {
		"color": {
			"background": "var(--wp--preset--color--base)",
			"text": "var(--wp--preset--color--contrast)"
		},
		"spacing": {
			"padding": {
				"left": "1.5rem",
				"right": "1.5rem"
			}
		},
		"typography": {
			"lineHeight": "1.6"
		}
	}
}

Output is valid and updates as you type.

Write a block theme’s theme.json: the presets editors pick from, the widths blocks align to, and the controls you want to leave them.

How to use

  1. Start with the format version. 3 is current and needs WordPress 6.6; pick 2 only if the site is older.
  2. Add your colours. Each row becomes an editor swatch and a --wp--preset--color--<slug> custom property, so the slug is a public name: keep it short and do not rename it later.
  3. Decide what you are taking away. Turning off custom colours and the WordPress palette is what makes a theme feel designed rather than configurable.
  4. Set the two widths. Content width is what a normal block gets; wide width is what the wide alignment stretches to.
  5. Add font sizes, then choose whether fluid typography turns each one into a clamp(). Fluid is on by default here because it is the cheaper way to be responsive.
  6. Copy the output to theme.json in your theme folder. Reload the editor: presets appear immediately, no cache to clear.

Example

The defaults give a three colour theme with its own font sizes and nothing else offered:

{
	"$schema": "https://schemas.wp.org/trunk/theme.json",
	"version": 3,
	"settings": {
		"appearanceTools": true,
		"color": {
			"custom": false,
			"customGradient": false,
			"defaultPalette": false,
			"palette": [
				{ "color": "#FFFFFF", "name": "Base", "slug": "base" },
				{ "color": "#111111", "name": "Contrast", "slug": "contrast" },
				{ "color": "#1E56EC", "name": "Accent", "slug": "accent" }
			]
		},
		"layout": { "contentSize": "645px", "wideSize": "1340px" },
		"useRootPaddingAwareAlignments": true
	},
	"styles": {
		"color": {
			"background": "var(--wp--preset--color--base)",
			"text": "var(--wp--preset--color--contrast)"
		}
	}
}

The body colours point at the presets rather than repeating the hex, so changing the Base row changes the page background too.

Pitfalls

  • Version 3 changed what a font size list means. In 2, declaring fontSizes replaced WordPress’s own; in 3 they are added to yours unless defaultFontSizes is false. The same applies to spacing sizes.
  • A child theme’s theme.json overrides the parent per key, not per value. Give settings.color.palette and you replace the parent’s entire palette, not just the colours you listed.
  • Preset slugs are part of your CSS API. var(--wp--preset--color--accent) is what patterns, user styles and custom CSS refer to; renaming a slug breaks all of them silently.
  • A name with accents or non-Latin characters cannot become a slug on its own. Type the slug yourself for those rows, or you get the letters that survived.
  • useRootPaddingAwareAlignments only does anything if styles.spacing.padding is set. On its own it is inert.
  • Changes an editor makes in the Site Editor are stored in the database and win over the file. Your theme.json edits will look ignored until those user styles are reset.
  • settings.color.custom: false hides the picker but does not remove colours already saved in content. Old posts keep their inline hex values.
  • Fluid typography rewrites every size, including ones you set with clamp() yourself. Turn it off per preset, or leave your own clamp out of a fluid theme.

Compatibility

theme.json needs WordPress 5.8; schema version 2 needs 5.9 and version 3 needs 6.6. useRootPaddingAwareAlignments and fluid typography both arrived in 6.1. appearanceTools needs 6.0. defaultPalette has been available since 5.9, defaultFontSizes and defaultSpacingSizes since 6.6. Everything written here is plain JSON with no theme-specific keys, so it works in a parent or a child theme. The tool runs entirely in your browser.

Frequently asked questions

Where does the file go?
In the theme folder root, next to style.css. Block themes read it automatically; classic themes can use it too, for settings only.
Why is my palette showing extra colours?
defaultPalette is on, so WordPress adds its own. Turn it off to offer only yours.
Do I need styles as well as settings?
No. settings defines what is available, styles sets what is used. A theme can ship settings alone and let patterns do the rest.
How do I check what WordPress made of it?
The Styles panel in the editor shows the resolved values, and the front end has them as custom properties on :root under --wp--preset--.
Can I delete a preset later?
You can, but content already using it keeps the class name and loses the colour. Change the value behind a slug instead of removing the slug.

From the people who built this tool

WP Adminify

The WordPress admin, rebuilt: a dashboard worth looking at, menu and column control, a real file manager and the login page your client sees.

See WP Adminify Free version on WordPress.org

Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.