Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis.

The theme.json file offers a wide range of customization options that make our lives much easier. Most of its properties map directly to WordPress-generated CSS variables, which we commonly use for colors, fonts, and layout settings. But its capabilities go far beyond our basic use.

With theme.json, we can:

  • Modify styles for WordPress core blocks
  • Create custom design variables
  • Assign those variables to custom blocks
  • Potentially reduce or even eliminate the need to modify stylesheets when developing new sites (unless we’re heavily customizing a block)

In short, theme.json can become a centralized system for controlling design across an entire project.

Let’s explore how this works in practice using a custom ACF accordion block.

Traditional Styling

Normally, when styling a custom block like an accordion, our stylesheet use Sass variables. We now have many of our basic Sass variables linked to WordPress presets from the theme.json.

So a standard workflow would go something like this:

  • Define variables in Sass
  • Reference WordPress presets (if any)
  • Apply styles directly in component stylesheets

With our traditional styling approach, our accordion stylesheet looks something like this:

While this works well, the styling remains mostly tied to the stylesheet itself. If we’re starting a new project and need to make site wide changes, we typically need to update styles across several Sass files.

But what if we could push more of that control into theme.json?

Using Custom Variables

Instead of relying solely on Sass variables, we can define custom properties directly inside theme.json. These generate WordPress CSS variables that we can use in our components.

A key detail here is the nesting structure of the configuration. The structure directly determines how WordPress names the generated CSS variables.

How WordPress Generates CSS Variables

WordPress always prefixes its generated variables with:

  • --wp--preset for predefined values (like colors or font sizes)
  • --wp--custom for custom settings

Each nested property becomes part of the variable name:

  • Nested objects are separated by double dashes (--)
  • camelCase properties convert to kebab-case (single dash)

For example, preset color variables defined in theme.json (under settings.color.palette) are referenced like this:

var(––wp––preset––color––primary);
var(––wp––preset––color––gray–dark);

Example: Custom Accordion Variables

Using a custom accordion configuration in theme.json, WordPress might generate variables like:
var(––wp––custom––accordion––color);
var(––wp––custom––accordion––background–color);
var(––wp––custom––accordion––border–radius);

We can then assign these variables directly to our accordion styles:

This approach makes the accordion’s design fully configurable from theme.json. Colors, backgrounds, borders, spacing, and other properties can all be controlled from a single configuration file.

Centralize Design

Once our component uses these generated variables, nearly every design aspect of the accordion can be preset in theme.json. We could dramatically change its appearance by editing a single configuration file, without touching component styles.

This creates a more centralized and scalable design system where:

  • Components remain flexible
  • Design tokens live in one place
  • Styling becomes easier to manage across projects

To illustrate, we could even push the styles to extreme values and instantly see the visual changes:

default-styles
Default
modified-styles
Modified

Whats the point?

At this point, you might be thinking:
“This is cool, but why go through all this trouble when we can just edit styles directly in our Sass files?”

And that’s a fair point. For many projects, this can feel like overkill. If we’re working on a single site with limited design variation, editing Sass directly is often simpler. Many of the advantages aren’t fully realized unless we have the Editor mode enabled in our theme. Which we have disabled because we don’t want to give our clients that much freedom when editing the sites we build. Many already have style guides that aren’t going to change.

However, the real power of theme.json becomes clear when thinking about scalability and theme maintenance.

Theme Variations

A more practical use case for this approach is creating reusable themes.

For example, we’ve discussed building a dedicated theme for Sound Transit. Traditionally, we might consider:

  • Creating a separate repository
  • Building a child theme
  • Maintaining multiple theme variations

Each option introduces scalability and maintenance challenges.

With theme.json, we could instead create different configuration files for different clients or brands. A Sound Transit theme.json could define:

  • Brand colors
  • Typography
  • Button styles
  • Layout settings
  • Component designs

We could then load that configuration into a fresh project using our latest boilerplate and instantly control most of the site’s visual appearance.

In practice, a single file swap could complete 80% (or more) of the design setup.

Why This Matters

Using theme.json as a design system provides several long-term benefits:

  • Centralized design control across components
  • Faster site setup for new projects
  • Reduced stylesheet maintenance
  • More scalable theme architecture

While it may feel unnecessary for smaller projects today, it opens the door to more flexible and reusable development workflows in the future.

LOE to migrate

The upfront cost to add all our blocks and relevant styles may be a heavy lift, but once that’s done it would just need to be maintained and updated with new blocks or mods to our existing ones. It’s hard to estimate what a full site conversion would take. We could keep it as simple or complicated as we want, taking anywhere from a few hours to a couple of days.

Compromise

One of the big benefits of the theme.json is just how flexible it is. We can do half measures here. We don’t need to do a complete conversion of all our blocks into the theme.json for styling.

We already began some conversion with our colors and font-family. We could push that a bit further with spacing, font sizes, specific blocks like buttons, and/or some core blocks.

References & Resources