So far, we’ve spent time getting familiar with theme.json
, the foundation for all WordPress block themes. We covered the various JSON data types and common terminology related to working with the JSON syntax.
We are going to build on that knowledge in this article.
WordPress Block Theme CSS and Style Settings Guide
Table of contents
What we mean by “top level”
We discussed how JSON has a structured syntax. We can see that in the basic outline of the theme.json
file:
{
"version": 2,
"settings": {},
"styles": {},
"customTemplates": {},
"templateParts": {}
}
Each object in the basic outline is a “top level” of the file. You can think of the objects as sections where various things are configured. Disregarding the version
, there are four top-level sections:
settings
: This is where we define WordPress presets and defaults; it’s also where we can enable or disable certain WordPress features.styles
: This is where we define CSS for global and block-level theme styles.customTemplates
: This is where we register new custom theme templates. It’s the equivalent of dropping a new PHP template file in a classic theme.templateParts
: This section contains modular pieces that can be included in templates. It’s the equivalent of theparts
subfolder you typically see in classic themes.
We’re spending most of our time in the settings
and styles
sections. Both provide ways to configure the global styles of a WordPress block theme. So, let’s look at each one and the various options we have to customize the theme appearance.
settings
)
The settings section (Again, this is where we configure WordPress features, sort of like the add_theme_support
function you’d reach for in a classic theme’s functions.php
file.
{
"version": 2,
"settings": {
// etc.
}
}
Why is this relevant to a theme’s global styles? Several WordPress features affect styling, like UI controls for padding, margins, colors, and fonts. Without enabling those, there’s no way to apply these and other styles in the Global Styles UI in the Site Editor.
In short: what we define here is what WordPress uses to add theme support for the Site Editor’s global style settings that are used throughout the theme.
Supported features
The WordPress Block Editor Handbook provides a table that outlines available features we can enable in the settings
section and compares them to their equivalent add_theme_support
function arguments.
Theme JSON settings | add_theme_support |
---|---|
color.custom | custom-colors |
color.palette | editor-color-palette |
color.gradients | editor-gradient-presets |
spacing.padding | custom-spacing |
spacing.units | custom-units |
typography.lineHeight | custom-line-height |
typography.fontSizes | editor-font-sizes |
useRootPaddingAwareAlignments | N/A |
For example, you were using add_theme_support
in your classic theme to disable custom font sizes:
<?php
add_theme_support(disable-custom-font-sizes);
The equivalent in theme.json
is the settings.typography.customFontSize
property:
{
"version": 2,
"settings": {
"typography": {
"customFontSize": false;
}
}
}
As you might imagine, there are nested features within these features. For example, if we were adding support for spacing
controls, there are a number of spacing
-related features we can individually enable:
{
"version": 2,
"settings": {
"spacing": {
"margin": false,
"padding": false,
"blockGap": null,
"units": [ "px", "em", "rem", "vh", "vw" ]
},
}
}
As of WordPress 6.1, these are the settings
features that can be configured in theme.json
:
View full table
Setting | Feature | Data type |
---|---|---|
border | radius | Boolean |
color | Boolean | |
style | Boolean | |
width | Boolean | |
color | custom | Boolean |
customDuotone | Boolean | |
customGradient | Boolean | |
duotone | Array | |
gradients | Array | |
link | Boolean | |
palette | Array | |
text | Boolean | |
background | Boolean | |
defaultGradients | Boolean | |
defaultPalette | Boolean | |
layout | contentSize | String |
wideSize | String | |
type | String (default and constrained ) | |
spacing | margin | Boolean |
padding | Boolean | |
blockGap | String | |
units | Array | |
typography | customFontSize | Boolean |
lineHeight | Boolean | |
dropCap | Boolean | |
fontStyle | Boolean | |
fontWeight | Boolean | |
letterSpacing | Boolean | |
textDecoration | Boolean | |
textTransform | Boolean | |
fontSizes | Array | |
fontFamilies | Array |
There are ongoing discussions to add the outline
and border
properties to the Global Styles panel. They are included in this table before formal adoption.
appearanceTools
shorthand
The I know that the table shows a ton of features. Configuring each setting could get cumbersome. That’s where the appearanceTools
setting comes into play.
{
"version": 2,
"settings": {
"appearanceTools": true
}
}
Setting it to true
enables the following settings in one fell swoop:
{
"version": 2,
"settings": {
"border": {
"color": true,
"radius": true,
"style": true,
"width": true
},
"color": {
"link": true
}
"spacing": {
"margin": true,
"padding": true,
"blockGap": true,
},
"typography": {
"lineHeight": true
}
}
}
You can see how many lines of code we can save this way! But let’s say you want to take advantage of appearanceTools
, but disable one or two of its supported features. You can do that on an individual basis to override that particular setting:
{
"version": 2,
"settings": {
"appearanceTools": true,
"border": {
"radius": false
}
}
}
The following screenshot shows how setting appearanceTools
to true
exposes those controls in the Global Styles UI, taken from the default Twenty Twenty-Three theme.
This Learn WordPress video by Nick Diego explains the appearanceTools
properties and the Global Styles interface in great detail.
Padding-aware alignments
This feature is worth calling out because it shipped more recently than many other features as part of WordPress 6.1. It is another shortcut for setting two spacing
features.
So, this:
{
"version": 2,
"settings": {
"useRootPaddingAwareAlignments": true
}
}
…is the equivalent of this:
{
"version": 2,
"settings": {
"spacing": {
"margin": true,
"padding": true
},
}
}
The real benefit of useRootPaddingAwareAlignments
is in the name. By enabling it, we opt into a feature that defines global padding on the <body>
of our theme and allows blocks to “break out” of that padding and go full-width if we need a block to span edge-to-edge.
See my previous article for a detailed overview of padding-aware alignments.
Configuring preset values
Presets are predefined values used by Global Styles features. More specifically, they define CSS custom properties used throughout a block theme.
So, let’s say you are defining your block theme’s default color palette and add black (#000000
) to it:
{
"version": 2,
"settings": {
"color": {
"palette": [
{
"color": "#000000",
"name": "Base",
"slug": "base"
}
]
}
}
}
Behind the scenes, something called the Style Engine takes those values and generates the theme’s CSS classes and custom properties. I described the Style Engine in a previous article:
The Style Engine is a new API in WordPress 6.1 that is meant to bring consistency to how styles are generated and where styles are applied. In other words, it takes all of the possible sources of styling and is singularly responsible for properly generating block styles. […] Having a centralized API for styles is probably the most elegant solution given that styles can come from a number of places.
When the Style Engine notices our styles
, it creates a set of preset custom properties. For example, that color palette example above? It produces a CSS custom property based on the information we supply it.
If we were to open up DevTools and inspect the <body>
element, we would see our custom properties there:
Notice how the custom property names are formatted:
--wp-preset--<feature>--<slug>: <value>
So, going back to our original example where we defined black in a color palette:
"color": {
"palette": [
{
"color": "#000000",
"name": "Base",
"slug": "Base"
}
]
}
We can expect to find this custom property applied to the <body>
element:
body {
--wp--preset--color--base: #000000;
}
All we’ve looked at are settings.color
presets, but nearly every value we define in the settings
section results in a custom property:
{
"version": 2,
"settings": {
"spacing": {
"spacingSizes": [
{
// Creates: --wp-preset--spacing--40: 1rem
"slug": "40",
"size": "1rem",
"name": "Small"
},
// etc.
]
}
}
}
Global presets
Now that we know how to define preset values in theme.json
, you might want to know what presets are available. The following table outlines what is currently available as of this writing and what they produce.
Setting | Feature | CSS custom property | CSS class |
---|---|---|---|
color | duotone | N/A | N/A |
gradients | --wp-preset--gradient--<preset-slug> | .has-<preset-slug>-<preset-category> | |
palette | --wp--preset--palette--<preset-slug> | Three classes per value:.has-<preset-value>-color .has-<preset-value>-background-color .has-<preset-value>-border-color | |
spacing | spacingScal e | N/A | N/A |
spacingSizes | --wp--preset--spacing--<preset-slug> | .has-<preset-slug>-spacing | |
typography | fontSizes | --wp--preset--font-size--<preset-slug> | .has-<preset-slug>-font-size |
fontFamilies | --wp--preset--font-family--<preset-slug> | .has-<preset-slug>-font-family |
Block presets
We can get more granular when defining preset values in theme.json
. In addition to the global presets we just saw, we can define presents at the block level.
Let’s say we have the following global color presets:
{
"version": 2,
"settings": {
"color": {
"palette": [
{
// --wp-preset--color--base: #ffffff
"color": "#FFFFFF",
"name": "Base",
"slug": "base"
},
{
// --wp-preset--color--contrast: #000000
"color": "#000000",
"name": "Contrast",
"slug": "contrast"
}
]
}
}
}
The custom properties generated by those settings are used throughout the theme, including blocks. So, if we were to add a Separator block to a page in the Block Editor, it will refer to the same color palette when it renders.
But we can override that palette — or any of the others in the global settings
— with a palette specifically for the Separator block:
{
"version": 2,
"settings": {
"color": {
"palette": [ // etc. ]
},
"blocks": {
"separator": {
"color": {
"palette": [
{
"color": "#F8A100",
"name": "Orange",
"slug": "orange"
}
]
}
}
}
}
}
In this example, the Separator block’s palette overrides the global palette with a single orange (#F8A100
) color value.
Custom presets
You can also create “custom” CSS custom properties on any property. In addition to the settings
features we’ve looked at so far, there is a custom
property where we can do that.
{
"version": 2,
"settings": {
"custom": {
// etc.
}
}
}
The Style Engine takes anything we define in there and generates CSS custom properties from it. The naming convention is pretty similar to the custom properties generated by the other settings:
--wp--custom--<variable-name>: <value>
Your defined values in custom
will be transformed into CSS custom properties and use the --wp--custom--<variable-name>
naming convention.
Here’s an abbreviated example of custom settings pulled straight from the default Twenty Twenty-Two theme. In it are custom settings for typography.font-size
and typography.line-height
:
{
"version": 2,
"settings": {
"custom": {
"typography": {
"font-size": {
"huge": "clamp(2.25rem, 4vw, 2.75rem)",
"gigantic": "clamp(2.75rem, 6vw, 3.25rem)",
"colossal": "clamp(3.25rem, 8vw, 6.25rem)"
},
"line-height": {
"tiny": 1.15,
"small": 1.2,
"medium": 1.4,
"normal": 1.6
}
}
}
}
}
Wrapping up
We learned a great deal about the settings
section of the theme.json
file. We covered the available settings and how they are used to define global styles that are used in the Global Styles UI of the WordPress Site Editor. From there, we learned about preset values, including which ones we can configure and how they are generated into CSS custom properties by the Style Engine.
What we haven’t covered is how we can use theme.json
to define CSS styles in a block theme. That happens in another top-level section called styles
, which is the focus of the next part of this series.