Defining Global Custom CSS Variables in theme.json
Standard presets in theme.json are strictly categorized (Color, Typography, Spacing). But often developers need global variables for things that don't fit those boxes, such as:
- Border Radius values
- Transition speeds
- Shadow depths
- Container widths
The solution is the settings.custom object.
1. The settings.custom Object
You can add any arbitrary JSON structure under settings.custom. WordPress will recursively crawl this object and generate CSS variables for every leaf node.
Syntax Formula:
--wp--custom--{parent}--{child}
Example Configuration
{
"version": 3,
"settings": {
"custom": {
"animation": {
"fast": "0.2s ease",
"slow": "0.5s ease-in-out"
},
"shadow": {
"card": "0px 4px 10px rgba(0,0,0,0.1)",
"popover": "0px 10px 40px rgba(0,0,0,0.2)"
},
"radius": {
"small": "4px",
"large": "12px"
}
}
}
}
2. The Generated CSS
WordPress outputs this in the <body> selector:
body {
--wp--custom--animation--fast: 0.2s ease;
--wp--custom--animation--slow: 0.5s ease-in-out;
--wp--custom--shadow--card: 0px 4px 10px rgba(0,0,0,0.1);
--wp--custom--radius--small: 4px;
/* ...etc */
}
3. How to Use Them
You can reference these variables anywhere in your theme.json styles or your external CSS files.
In theme.json (Styles)
"styles": {
"blocks": {
"core/button": {
"border": {
"radius": "var(--wp--custom--radius--small)"
}
},
"core/group": {
"shadow": "var(--wp--custom--shadow--card)"
}
}
}
In style.css
.my-custom-component {
transition: all var(--wp--custom--animation--fast);
box-shadow: var(--wp--custom--shadow--popover);
}
4. Why Use This Instead of style.css :root?
- Centralization: All your design tokens (colors, fonts, and custom values) live in one file (
theme.json). - Editor Support: Gutenberg is aware of these values. While there isn't a UI picker for them yet, they are loaded in the iframe editor, ensuring your blocks look correct on the backend.