Theme.json color options

Level: ,

Estimated reading time: 17 minutes

In this lesson, you will learn how to use all the theme.json color options, including:

  • Site-wide and block specific color palettes
  • Enable or disable custom colors (color picker)
  • Enable or disable gradients, duotone, link- and border colors
  • Adding default colors to blocks

At the end of the lesson, you will also find answers to frequently asked questions.

Prerequisites: Global Styles & theme.json.

Updated June 25, 2022.

Introduction

What color options can you change with theme.json?

The WordPress block editor has many different types of color options:

  • Background color: Solid and gradient
  • Text color
  • Link text color
  • Border color
  • Inline text color (Highlight)
  • Duotone
  • Cover block overlay
The default color panel in the block settings sidebar.

With theme.json, you can:

  • Decide which colors, gradients, and duotones the user can choose from
  • Decide if the user should be able to select custom colors using the color picker
  • Disable and enable link color, border colors, gradients, and duotones
  • Use different color options per block
  • Apply default colors to many blocks

What colors can you not change with theme.json?

You may run into problems when you apply colors to complex blocks with multiple HTML elements. For example, in a block like the latest posts block you can not add different colors for the post date and post author.

What color values can you use in theme.json?

Except for duotones, you can use any valid CSS color values to add or apply colors. Such as hex, rgb, rgba, color names like blue or red, keywords like transparent and currentColor, hsl, and hsla. You can also use a CSS custom property.

Duotone only works with hex and rgb color values.

JSON structure

All three color options: the palette, duotone, and gradients use the same JSON structure with key and value pairs:

  • slug: The unique identifier, also used in the CSS custom property.
  • name: The visible name of the color in the editor.
  • color/gradient/duotone: The CSS color value.

Color palettes

Since Gutenberg version 11.9, the block editor shows three separate color palettes: The default, the theme palette, and a palette of colors added by the user in the global styles interface.

The default color palette

WordPress registers colors in its default color palette with CSS custom properties that are available for all themes. This is so the default colors don’t break if the user switches themes, and to make it easier for us to use patterns from the pattern directory.

The palette is persistent: even if you hide it or add a new color palette, the CSS custom properties for these colors remain.

View the default colors

–wp–preset–color–black: #000000;

–wp–preset–color–cyan-bluish-gray: #abb8c3;

–wp–preset–color–white: #ffffff;

–wp–preset–color–pale-pink: #f78da7;

–wp–preset–color–vivid-red: #cf2e2e;

–wp–preset–color–luminous-vivid-orange: #ff6900;

–wp–preset–color–luminous-vivid-amber: #fcb900;

–wp–preset–color–light-green-cyan: #7bdcb5;

–wp–preset–color–vivid-green-cyan: #00d084;

–wp–preset–color–pale-cyan-blue: #8ed1fc;

–wp–preset–color–vivid-cyan-blue: #0693e3;

–wp–preset–color–vivid-purple: #9b51e0;

How to hide the default color palette

You can hide the default palette in the editor by setting it to false in settings.color:

{
	"version": 2,
	"settings": {
		"color": {
			"defaultPalette": false
		}
	}
}

Or, hide it for a single block type:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/paragraph": {
				"color": {
					"defaultPalette": false
				}
			}
		}
	}
}

How to add a new color palette to the block editor

You can create a new color palette inside settings.color in theme.json:

settings.color.palette

You list the palette colors inside an array, encasing them with curly brackets and separating them with a comma:

{
	"version": 2,
	"settings": {
		"color": {
			"palette": [
				{
					"slug": "primary",
					"color": "#7c027c",
					"name": "Purple"
				},
				{
					"slug": "secondary",
					"color": "#420142",
					"name": "Dark purple"
				}
			]
		}
	}
}

WordPress parses the JSON and creates a CSS custom property for each color, and adds them to the <body> element:

body {
    --wp--preset--color--primary: #7c027c;
    --wp--preset--color--secondary: #420142;
}

These properties are available in addition to the custom properties for the default palette.

How to add a color palette for a block

You can create separate color palettes for blocks under the blocks section inside the settings section:

settings.blocks.blockname.color.palette

Example:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/paragraph": {
				"color": {
					"palette": [
						{
							"slug": "primary",
							"color": "#7c027c",
							"name": "Purple"
						},
						{
							"slug": "secondary",
							"color": "#420142",
							"name": "Dark purple"
						}
					]
				}
			}
		}
	}
}

The block specific CSS custom properties are not added to the <body>, but to the block selector:

p {
    --wp--preset--color--primary: #7c027c;
    --wp--preset--color--secondary: #420142;
}

How to disable color palettes

There are a few different ways to disable color palettes and color palette options.

New in Gutenberg 11.5, you can disable background, text, and link colors separately:

{
	"version": 2,
	"settings": {
		"color": {
			"background": false,
			"link": false,
			"text": false,
		}
	}
}

The link color is disabled (false) by default, but added here as an example.

Here is an example of how to disable the background color for a single block type.
With this example, the palette for the text color is still available unless it has been disabled globally.

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/paragraph": {
				"color": {
					"background": false
				}
			}
		}
	}
}

Read more about this change on GitHub.

You can remove the color palette for all blocks by leaving the array of colors empty:

{
	"version": 2,
	"settings": {
		"color": {
			"palette": []
		}
	}
}

Or you can remove it for a single block:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/paragraph": {
				"color": {
					"palette": []
				}
			}
		}
	}
}

How to disable the custom color picker

You can disable custom colors (the color picker) for all blocks by setting color.custom to false inside the settings section:

{
	"version": 2,
	"settings": {
		"color": {
			"custom": false
		}
	}
}

Here is how you would disable custom colors for a single block:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/paragraph": {
				"color": {
					"custom": false
				}
			}
		}
	}
}

You can use the following code to disable the color picker for all blocks except the paragraph:

{
	"version": 2,
	"settings": {
		"color": {
			"custom": false
		},
		"blocks": {
			"core/paragraph": {
				"color": {
					"custom": true
				}
			}
		}
	}
}

Only a few blocks support the border color and link color controls in the editor. You can still set default colors with theme.json, but the user can’t change the colors.

{
	"version": 2,
	"settings": {
		"border": {
			"color": true
		},
		"color": {
			"link": true
		}
	}
}

You can also enable this site-wide, but disable it for specific blocks.
Switch the true and false values to disable link color site-wide and enable them for the single block. The border color option works the same way.

{
	"version": 2,
	"settings": {
		"color": {
			"link": true
		},
		"blocks": {
			"core/list": {
				"color": {
					"link": false
				}
			}
		}
	}
}

Duotone

Duotone is a filter where you pair two colors to create effects for videos and images.
From Gutenberg 11.7, duotones use a CSS custom property in the following format:

--wp--preset--duotone--slug

Read more about the introduction of duotones in WordPress:

WordPress.org: Coloring Your Images With Duotone Filters

WP Tavern: Duotone Filters: WordPress 5.8 Puts a Powerful Image-Editing Tool Into Users’ Hands

As one of the newest color filters, duotone does have some bugs.
The Gutenberg developers are exploring solutions for known issues with transparency for duotones, and duotones for fixed backgrounds.

Which WordPress blocks support duotone?

The cover block, image, featured image, avatar and site logo supports duotone (June 2022).

Default duotones

Dark grayscale

The WordPress default duotone applied to an image of wapuu.

Grayscale

Purple and yellow

Blue and red

Midnight (Black and blue)

Magenta and yellow

Purple and green

Blue and orange

How to add duotone colors

You can add new duotones inside the settings section of theme.json:

settings.color.duotone

In comparison to the color palette which takes one color value, the duotone takes an array with two color values. So the first color is the shadow, and the second color is the highlight.
Separate the values with a comma.

Important: Duotone only works with the hex and rgb color formats:

"colors": [ "#cc1871", "#f9449e" ]

If you add more than two colors, the effect will only use the first two colors.

Example of how to add a new duotone for all blocks that support the feature (site-wide):

{
	"version": 2,
	"settings": {
		"color": {
			"duotone": [
				{
					"colors": [ "#cc1871", "#f9449e" ],
					"slug": "pink-and-light-pink",
					"name": "Pink and light pink"
				}
			]
		}
	}
}

And for a single block:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/cover": {
				"color": {
					"duotone": [
						{
					"colors": [ "#cc1871", "rgb(255,255,255)" ],
							"slug": "pink-and-white",
							"name": "Pink and white"
						}
					]
				}
			}
		}
	}
}

How to disable duotone

You need to add an empty duotone color array and set color.customDuotone to false to completely disable duotone:

  • "duotone": [] disables the palette
  • "customDuotone": false disables the color picker
{
	"version": 2,
	"settings": {
		"color": {
			"duotone": [],
                        "customDuotone": false
		}
	}
}

How to disable duotone for a single block:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/cover": {
				"color": {
					"duotone": [],
					"customDuotone": false
				}
			}
		}
	}
}

To only disable custom duotones (the color picker), you can set color.customDuotone to false:

{
	"version": 2,
	"settings": {
		"color": {
			"customDuotone": false
		}
	}
}

How to disable the custom duotone color picker for single blocks:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/image": {
				"color": {
					"customDuotone": false
				}
			}
		}
	}
}

How to set a default duotone using theme.json

New in Gutenberg 11.7, you can set a default duotone for the supported blocks. In this example I am using one of the default duotones with the image block:

{
	"version": 2,
	"styles": {
		"blocks": {
			"core/image": {
				"filter": {
			"duotone": "var(--wp--preset--duotone--magenta-yellow)"
				}
			}
		}
	}
}

Gradients

Which WordPress blocks support gradient backgrounds?

Button, code, column, columns, comment author name, comment content, comment date, comment edit link, comment reply link, comments pagination, comments title, comments query loop, group, list, media & text, post author biography, post author name, post author, post comments count, post comments form, post comments, post date, post excerpt, post terms, post title, preformatted, pullquote, no results, query pagination, query pagination, archive title, post list (query), quote, read more, search, separator, site tagline, site title, table, and verse. The cover block supports gradients as overlays (June 2022).

Default gradients

The default gradients are persistent as the CSS custom properties are output even if you disable gradients in your theme. This prevents the colors from breaking if the user has used the gradients and then changes themes.

–wp–preset–gradient–vivid-cyan-blue-to-vivid-purple:
linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);

–wp–preset–gradient–light-green-cyan-to-vivid-green-cyan:
linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);

–wp–preset–gradient–luminous-vivid-amber-to-luminous-vivid-orange:
linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);

–wp–preset–gradient–luminous-vivid-orange-to-vivid-red:
linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);

–wp–preset–gradient–very-light-gray-to-cyan-bluish-gray:
linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);

–wp–preset–gradient–cool-to-warm-spectrum:
linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,
rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);

–wp–preset–gradient–blush-light-purple:
linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);

–wp–preset–gradient–blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);

–wp–preset–gradient–luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);

–wp–preset–gradient–pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);

–wp–preset–gradient–electric-grass:
linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);

–wp–preset–gradient–midnight:
linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);

How to hide the default gradients

{
	"version": 2,
	"settings": {
		"color": {
			defaultGradients": false
		}
	}
}

How to add gradients to the block editor

You add gradients under the settings section of theme.json:

settings.color.gradients

Use any valid CSS gradient: linear, radial, conic, or repeating, with any number of colors and opacity. Example:

{
	"version": 2,
	"settings": {
		"color": {
			"gradients": [
				{
					"slug": "pink-to-pale-purple",
					"gradient": "linear-gradient(to bottom right,rgba(255,30,142) 49.9%,rgb(229,6,229, 0.36) 50%)",
					"name": "Diagonal pink to pale purple"
				}
			]
		}
	}
}

You can also experiment with different shapes and hard stops:

CSS output:

body {
--wp--preset--gradient--pink-to-pale-purple: linear-gradient(to bottom right,rgba(255,30,142) 49.9%,rgb(229,6,229, 0.36) 50%);
}

How to add gradients for different WordPress blocks:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/group": {
				"color": {
					"gradients": [
						{
							"slug": "pink-to-pale-purple",
							"gradient": "linear-gradient(to bottom right,rgba(255,30,142) 49.9%,rgb(229,6,229, 0.36) 50%)",
							"name": "Diagonal pink to pale purple"
						}
					]
				}
			},
			"core/search": {
				"color": {
					"gradients": [
						{
							"slug": "white-to-grey",
							"gradient": "linear-gradient(90deg, rgb(255,255,255) 0%, rgb(203,203,203) 49%, rgb(255,255,255) 98%)",
							"name": "White to grey"
						}
					]
				}
			}
		}
	}
}

CSS output:

.wp-block-group {
    --wp--preset--gradient--pink-to-pale-purple: linear-gradient(to bottom right,rgba(255,30,142) 49.9%,rgb(229,6,229, 0.36) 50%);
}

.wp-block-search {
    --wp--preset--gradient--white-to-grey: linear-gradient(90deg, rgb(255,255,255) 0%, rgb(203,203,203) 49%, rgb(255,255,255) 98%);
}

How to disable gradients

You need to add an empty gradients array and set color.customGradient to false to disable gradients site-wide:

{
	"version": 2,
	"settings": {
		"color": {
			"gradients": [],
			"customGradient": false
		}
	}
}

Next is an example of how to disable gradients for a single block:

{
	"version": 2,
	"settings": {
		"blocks": {
			"core/group": {
				"color": {
					"gradients": [],
					"customGradient": false
				}
			}
		}
	}
}

Applying colors with theme.json

In the first part of this lesson, we went through how to add color options to the editor.
Next, I will show you some practical examples of applying colors to blocks in the styles section of theme.json.

One thing to keep in mind is that you are not limited to using presets that you created in the settings section. You can use any valid CSS color value.

Text color

Colors on the root level of the styles section in theme.json are applied to the HTML body.

styles.color.text
{
	"version": 2,
	"styles": {
		"color": {
			"text": "var(--wp--preset--color--black)"
		}
	}
}

CSS Output:

body {
    color: var(--wp--preset--color--black);
}

The next example shows how to add a default text color to a single block:

{
	"version": 2,
	"styles": {
		"blocks": {
			"core/verse": {
				"color": {
					"text": "var(--wp--preset--color--black)"
				}
			}
		}
	}
}

And the resulting CSS output for the verse block is:

.wp-block-verse {
    color: var(--wp--preset--color--black);
 }

Background color

You add the body background color the same way you add the text color:

styles.color.background
{
	"version": 2,
	"styles": {
		"color": {
			"background": "var(--wp--preset--color--black)"
		}
	}
}

CSS output:

body {
    background-color: var(--wp--preset--color--black);
}

The code for adding a background for a single block is equally straightforward:

{
	"version": 2,
	"styles": {
		"blocks": {
			"core/search": {
				"color": {
					"background": "var(--wp--preset--color--black)"
				}
			}
		}
	}
}

CSS output:

.wp-block-search {
    background-color: var(--wp--preset--color--black);
}

How to add a default gradient background to a block

You can add default gradients to supported blocks using styles.color.gradient.

{
	"version": 2,
	"styles": {
		"blocks": {
			"core/heading": {
				"color": {
					"gradient": "var(--wp--preset--gradient--cool-to-warm-spectrum)"
				}
			}
		}
	}
}

CSS output:

h1, h2, h3, h4, h5, h6 {
    background: var(--wp--preset--gradient--cool-to-warm-spectrum);
}

Applying colors using theme.json elements

You use the elements object to apply styles to links, headings and buttons, independent of the block. Support for buttons was added in Gutenberg version 13.4.

Styling site wide links:

{
	"version": 2,
	"styles": {
		"elements": {
			"link": {
				"color": {
					"text": "var(--wp--preset--color--secondary)"
				}
			}
		}
	}
}

CSS output:

a {
    color: var(--wp--preset--color--secondary);
}

Use the heading levels H1 to H6 to add default colors to headings:

{
	"version": 2,
	"styles": {
		"elements": {
			"h1": {
				"color": {
					"text": "var(--wp--preset--color--secondary)"
				}
			}
		}
	}
}

CSS output:

h1 {
    color: var(--wp--preset--color--secondary);
}

Styling buttons:

{
	"version": 2,
	"styles": {
		"elements": {
			"button": {
				"color": {
					"text": "var(--wp--preset--color--secondary)",
					"background": "var(--wp--preset--color--primary)"
				},
				"border": {
					"color": "var(--wp--preset--color--pale-pink)"
				}
			}
		}
	}
}

You can also add background colors to links:

{
	"version": 2,
	"styles": {
		"elements": {
			"link": {
				"color": {
					"text": "white",
					"background": "#222222"
				}
			}
		}
	}
}

One use case for the link background color is to style the pagination.
Remember that when you apply styling to blocks, the styles first need to be placed inside the blocks object:

styles.blocks.blockname.elements.link.color.text
styles.blocks.blockname.elements.link.color.background
{
	"version": 2,
	"styles": {
		"blocks": {
			"core/query-pagination": {
				"elements": {
					"link": {
						"color": {
							"text": "#fff",
							"background": "#222"
						}
					}
				}
			}
		}
	}
}

Another use case for adding a background color to links is to highlight post titles and read more links, like in this example on Tammie Lister’s website ephemeralthemes.com:

A blog post listing where the post title and read more links has a high contrast yellow background color and a black link text.

Styling the post excerpt read more text can seem tricky. -First the block needs to have the link option enabled and a custom read more text, otherwise, there is no link element to style.

In this example, I have included padding to make the background color more visible:

{
	"version": 2,
	"styles": {
		"blocks": {
			"core/post-excerpt": {
				"elements": {
					"link": {
						"color": {
				"background": "var(--wp--preset--color--pale-cyan-blue)"
						},
						"spacing": {
							"padding": {
								"top": "0.6rem",
								"right": "1rem",
								"bottom": "0.6rem",
								"left": "1rem"
							}
						}
					}
				}
			}
		}
	}
}

Border color

Which WordPress blocks support borders?

All blocks can have a default border added in theme.json. The following blocks have support for border color, style, width, and radius: Avatar, code, columns, comments title, group, pull quote, read more and search.

The button block and image block have controls for border radius.
The table block and column has controls for style, width, and color, but not radius.

For the border controls to be visible in the editor, you need to enable the feature.

Button border controls in the block settings sidebar includes an input field for border width, a style selection option with solid, dashed and dotted.
Below is a color selection option and a border radius option with an input field and a range slider.

Border color examples

When you add a border color you also need to add a border style for the border to be visible:

{
	"version": 2,
	"styles": {
		"border": {
			"style": "solid",
			"color": "var(--wp--preset--color--pale-pink)"
		}
	}
}

One use case for adding borders to the body element could be for boxed layouts.

Button block and pull quote code examples:

{
	"version": 2,
	"settings": {
		"border": {
			"customColor": true,
			"customRadius": true,
			"customStyle": true,
			"customWidth": true
		}
	},
	"styles": {
		"blocks": {
			"core/button": {
				"border": {
					"style": "solid",
					"color": "var(--wp--preset--color--pale-pink)"
				}
			},
			"core/pullquote":{
				"border": {
					"width": "4px",
					"radius": "10px",
					"style": "dotted",
					"color": "var(--wp--preset--color--cyan-bluish-gray)"
				}
			}
		}
	}
}
A button block with a solid pink border, followed by a pullquoute block with a dotted gray border and rounded corners.

Frequently asked questions

How should I name the colors?

It is recommended to use primary, secondary, tertiary and so on as the color slug, because the slug is the unique identifier.
But the visible name can be a color name or description.
Example: “slug”: “primary”, “color”: “#7c027c”, “name”: “Purple”

If more themes use this naming convention, it will be easier for the user to change themes and keep the color contrast and readability of their existing content.

You can follow the discussion about best practices and the naming convention in this overview issue on GitHub: Default Colors, Theme Colors, and Custom Colors.

Can you use separate palettes for background and text color?

This is not possible with theme.json. There was a GitHub issue with a proposal to add contextual palettes, but the issue was closed with the comment that there are no plans to implement this.

Are there any plans to add gradient support to paragraphs?

This question has come up during different user testing sessions, and I have created an issue for adding gradients backgrounds to paragraph blocks.
There is also a discussion about possibly adding gradient text to headings.