Theme.json Color Slugs
Standardizing across Themes
This is part one, of three, in a series on standardizing how we build this next generation of WordPress block themes to accompany the Full Site Editing effort. If you like this, read on about standardizing font sizes, and standardizing site spacing. Each of these are what I would consider design foundations of a website, of which should be functionally standardized. I know —you’re probably thinking that by standardizing anything theme related, we’ll have unoriginal WordPress themes that lack creativity… but what if I told you that standardization would do just the opposite, and more.
By standardizing just a few key high-level entries within a WordPress theme’s theme.json file, we can finally create a class of themes that truly are interchangeable. Interchangeable in function, while remaining distinct in style. In particular, I’m referring to colors, font sizes, & site spacing — the design system components that every site leverages, theme.json based, or not. Let’s start making themes that act more like themes. So here’s my take on why this is important, and how we can get there.
Theme color palettes generated from theme.json
When a background color is applied to a block, a .has-{property}-background-color
class is added. Applying a text color works exactly the same way, but instead using the auto-generated .has-{property}-color
class. Within WordPress block themes, these colors are added using the theme.json file, within the settings.color.palette
object, like this:
{
"settings": {
"color": {
"palette": [
{
"slug": "primary",
"color": "#36C5F0",
"name": "Primary"
},
{
"slug": "secondary",
"color": "#2EB67D",
"name": "Secondary"
},
{
"slug": "base",
"color": "#fff",
"name": "Base"
},
{
"slug": "contrast",
"color": "#000",
"name": "Contrast"
}
]
},
}
}
The theme.json resolver creates the CSS classes with the appropriate value, along with the necessary custom properties to load within the block editor and on the front-end. The output looks of the above would look like this:
body {
--wp--preset--color--primary: #36C5F0;
--wp--preset--color--secondary: #2EB67D;
--wp--preset--color--base: #fff;
--wp--preset--color--contrast: #000;
}
.has-primary-background-color {
background-color: var(--wp--preset--color--primary) !important;
}
.has-primary-color {
color: var(--wp--preset--color--primary) !important;
}
.has-secondary-background-color {
background-color: var(--wp--preset--color--secondary) !important;
}
.has-secondary-color {
color: var(--wp--preset--color--secondary) !important;
}
.has-base-background-color {
background-color: var(--wp--preset--color--base) !important;
}
.has-base-color {
color: var(--wp--preset--color--base) !important;
}
.has-contrast-background-color {
background-color: var(--wp--preset--color--contrast) !important;
}
.has-contrast-color {
color: var(--wp--preset--color--contrast) !important;
}
This is great — as now themes don’t have to manually declare a set of CSS classes to cover colors. However, there is one caveat. If you switch to a different block theme, these specific color classes are no longer generated — leaving nothing in their place. This means that anywhere you’ve used the primary
color will result in no color at all — if the primary
color does not exist within the incoming theme. Not a fantastic experience. In fact — it’s kind of destructive.
Blocks themes don’t have to be built this way. As theme developers, we should encourage the democratization of publishing… even if that means making it easy for folks to switch away from your products.
Standard color slugs in theme.json
Just because all block themes should register at least base
, contrast
and perhaps primary
colors, does not mean that every theme will have black text, a white background, and a blue accent color.
That saying, here are the settings.colors.palette
slugs that I propose should be included in every block theme:
base
contrast
primary
(if the theme uses any other color)
The `base` color is appropriately the site’s background color. This makes it easy to manipulate within the theme.json file, as well as the upcoming Global Styles interface.
The foreground color is the base color of elements applied to the page. I’d include all headings, text, list items, captions, etc — as realistically, this value could be the fallback color for just about anything. Again, this empowers the user within Global Styles, as now all text elements may be modified quickly.
And last, the primary
is the block theme’s first accent color. And if a theme wants to add more colors, those should be registered sequentially, just like how the Clove theme does.
Sequential accent color slugs
Let’s take a deeper look at the Clove and Naledi themes. If I activate Clove, create a page with blocks, and style using the theme’s standardized color palette (which uses sequential accent color slugs) I can then switch to another theme that uses the same standardized format — and all the colors properly map to the new theme’s color palette, like this:


In the image above, I am using the tertiary
color for the pattern background and the primary
color for the border around the Image block. Those colors are accurately reflected in both themes, as I switch between them. Nice. Now if had two themes that did not support a method of standardization between color slugs, this is what I’d end up with, now switching from Clove, to the TT1 Blocks theme:


Right off you’ll notice how the tertiary
color I applied to the pattern’s top-level Group block is missing, and the primary
accent color applied to the Image block’s border is also gone. Not so nice anymore. I hope this illustrates how standardization helps the user. And sure, I understand that not every theme will include three accent colors — but systematizing base
, contrast
, and primary
slugs across block themes would certainly be a massive step in the right direction.
So why not use specific color slugs?
I’ve noticed that most block themes are rooting for slugs that are tied to a specific color — think green
for a theme’s accent color that is perhaps a fun shade of lime green. The downside here is that in a world of Global Style, that color value — which was hard-coded as green
— may easily be modified into any other color. Block themes are not the end-all-be-all when it comes to design — the user is.

In this most likely scenario, the green
color slug is now irrelevant, and the class generated from the slug is no longer appropriate — in fact, it’s misleading. The class insists the color applied is green in nature, with the .has-green-color
class, but the value may actually be any other color that the user has chosen.
What do you think?
And as we continue to move towards more block and pattern-based site building, we should encourage themes to act more as a coat of paint, not a system of locked-in design components. Moving the theme.json settings.colors.palette
object to use a standardized system of entries will support that effort and push us one step closer towards a friendlier WordPress theme ecosystem. If you’re interested, there’s an issue on GitHub that reflects much of this thinking, as a potential direction to head towards. Consider adding your voice to the mix whether you agree or not, your opinion matters.
If you like this article on colors, read the others in this standardization series covering font sizes and site spacing.