theme.json: Controlling a Block Theme Without Fighting It
Understand WordPress theme.json settings, styles and saved user overrides, then debug block-theme colours, spacing and typography in a repeatable order.

In this article
You change a colour in a block theme, clear the page cache and still see the old value. Adding a stronger CSS selector sometimes hides the symptom, but it does not explain which design setting produced the colour. The next editor change can bring the problem back.
WordPress theme.json provides a structured place to declare editor settings and design styles. It also participates in a system that includes core defaults, theme variations, saved user choices and block attributes. The useful skill is tracing one property through that system. This guide uses a small palette change as a working example and keeps configuration precedence separate from the final CSS cascade.
Start with one property and a reproducible page
Create a staging page containing a paragraph, heading, button and a Group block. Record the active theme, any child theme, the WordPress version and whether a style variation is selected. Choose one property to investigate, such as the button background, before changing several configuration files at once.
Compare a newly inserted button with the existing button that looks wrong. If only the older block is different, inspect its saved settings and classes. That is useful evidence that the block has its own colour choice. If both differ between the editor and frontend, look for styles loaded in only one environment or a stale generated asset.
Keep the block theme and classic theme comparison nearby if you are unsure which template and styling system the site uses. theme.json is a design configuration file; adding it does not automatically convert a classic theme into a complete block theme.
Use settings for choices and styles for their application
{
"$schema": "https://schemas.wp.org/wp/6.6/theme.json",
"version": 3,
"settings": {
"color": {
"custom": false,
"palette": [
{
"slug": "ink",
"name": "Ink",
"color": "#243b35"
},
{
"slug": "paper",
"name": "Paper",
"color": "#f7f3ea"
}
]
}
},
"styles": {
"color": {
"background": "var:preset|color|paper",
"text": "var:preset|color|ink"
}
}
}The settings section controls capabilities such as custom colours and defines presets such as a named palette. The styles section assigns values to the site, elements or supported blocks. You can expose a brand colour without making it the default text colour, and you can set a default without exposing every possible editing control.
The example defines two palette entries, disables the arbitrary custom-colour picker and applies those presets to global background and text. It illustrates a version 3 configuration, so check that the WordPress versions you support recognise that format and its settings. A JSON parser checks punctuation; schema validation checks whether the shape and properties are recognised.
Use stable preset slugs such as ink and paper. Content may store a reference to a preset, so renaming a slug can affect existing blocks even when the visible label seems unchanged. Decide which values are reusable design tokens and which are deliberate exceptions before exposing them to editors.
Distinguish configuration precedence from CSS specificity
WordPress combines configuration from several origins. Core supplies defaults, the active theme supplies its values, a child theme can take precedence over its parent, and saved user Global Styles can override theme choices. Plugins and registered block styles can also contribute. The core theme JSON resolver is a useful reference for the version you are running.
After that configuration is combined, WordPress generates CSS. Ordinary stylesheet rules, inline styles and block-level attributes still participate in the browser cascade. A configuration origin taking precedence is not the same operation as one selector beating another. Treating every mismatch as a specificity problem can leave the underlying user setting untouched.
In browser developer tools, inspect the exact element and expand the computed property. Follow the winning declaration to its stylesheet or inline source and inspect the referenced custom property. Record whether the unexpected value originates in a preset, an element style, a block rule or saved block markup. That narrows the next change considerably.
Build a modest design system before block exceptions
Define the palette, content widths, useful spacing steps and a small typography scale first. Give presets names that make sense to an editor. A scale with a few meaningful choices is easier to maintain than dozens of nearly identical values imported from an exploratory design file.
Check contrast for the actual foreground and background combinations the editor can create. A palette that contains accessible pairs can still permit inaccessible combinations. Test long headings, linked text, a button with two lines and content at a narrow viewport. If the design relies on a custom font, verify its licence, loading strategy and fallback metrics independently.
Document which decisions are global and which belong to a specific block. If every card needs the same spacing, encode the reusable pattern or block style rather than asking editors to reproduce a fragile series of manual overrides. The custom theme development guide covers the wider template and maintenance decisions.
Apply block and element styles deliberately
Global text styling is not a guarantee that every link, button or heading will inherit the intended appearance. Supported element styles and per-block styles give more precise control. Start with the smallest useful rule and inspect its generated selector instead of adding another site-wide CSS reset.
Create a fresh block and test the normal, hover and keyboard-focus states of interactive elements. Check nested Group blocks and a section with a different background. A rule that looks correct on an isolated paragraph may produce the wrong result inside an inherited colour context. Keep visible focus and link affordances when changing colours.
For custom blocks, declare supported features intentionally and use the relevant block wrappers and style APIs. A block that bypasses those mechanisms may not respond like a core block. The custom Gutenberg block guide explains the registration and rendering side; theme.json cannot repair arbitrary markup that ignores the design system.
Inspect saved user styles before resetting anything
A designer may have changed a palette or a block style in the Site Editor during an earlier review. That choice can be stored in the database and continue to affect output after you edit the theme file. Check the active style variation and the relevant Global Styles controls before deciding the file is being ignored.
On staging, export or otherwise preserve the current configuration and take a database backup before resetting user customisations. Reset only the relevant setting when possible. A broad reset can remove deliberate design work on unrelated pages. Compare the same test page before and after so you can connect the result to one intervention.
When the agreed design change should become part of the theme, move it into version-controlled theme configuration using a supported workflow and confirm that a clean installation reproduces it. A database-only styling fix may disappear when a colleague builds a fresh site from the repository.
Validate changes in the editor and the public release
Finish with a small acceptance checklist rather than a screenshot of the test page. Validate JSON against the supported schema, open the editor without console errors, check a new and existing block, and compare public output at the breakpoints used by real readers. Confirm that restricted controls are actually restricted for the relevant editing role.
Purge only the relevant generated CSS or hosting caches after you understand which layer changed. Cache clearing does not remove a saved user override, and a successful preview in one browser does not establish that the deployed theme contains your latest file. Check the deployed version and a fresh response where necessary.
Keep a short note explaining the original symptom, the winning declaration and the configuration change that resolved it. That note turns the next colour or spacing issue into a repeatable investigation. It is also a useful handover artefact for the person who will maintain the theme after the initial design project.
Frequently asked questions
What does theme.json do in a WordPress theme?
It declares design presets, editor settings and supported styles that WordPress combines with other configuration and uses to generate styling. It is part of the theme styling system, not a replacement for every stylesheet or block attribute.
Why is my CSS being overridden by theme.json?
Inspect the computed property and its source first. Saved Global Styles, a style variation, block attributes or a more specific stylesheet rule can affect the result through different layers.
How do I add custom colours and fonts in theme.json?
Add named presets under the relevant settings, then apply them through supported styles or editor selections. Keep preset slugs stable, validate against your supported version and test existing content.
Can I use theme.json in a classic theme?
Classic themes can adopt supported theme.json features. The available editing experience still depends on the theme and WordPress version; the file alone does not supply block templates or a complete Site Editor workflow.