Skip to main content
Adzbyte
TutorialsWordPress

Manage WordPress Design Tokens with theme.json

Adrian Saycon
Adrian Saycon
September 23, 20265 min read
Manage WordPress Design Tokens with theme.json

In WordPress, theme.json can serve as the executable source for design tokens: named colors, font sizes, spacing steps, layout widths, and component styles that appear in both the editor and front end. The goal is not to move every CSS declaration into JSON. It is to define stable choices once, expose only intentional controls, and let WordPress generate the corresponding presets and custom properties. This tutorial builds a small token system and shows where conventional CSS still belongs. It also gives custom blocks a shared vocabulary instead of isolated visual defaults.

Start with semantic decisions

A token should express a reusable design decision rather than a one-off visual value. “Brand,” “surface,” and “content width” are stronger contracts than “blue” or “742 pixels.” Semantic names allow implementation values to change without rewriting block markup.

Inventory the repeated colors, type sizes, spacing values, and widths in the current site. Consolidate near-duplicates before encoding them. A token file that preserves every historical inconsistency makes the inconsistency official. Keep a small inventory beside the theme: token name, intended usage, owner, and where an old value still appears. This helps distinguish a deliberate exception from accidental drift when a redesign changes the palette.

Choose a schema and version deliberately

Create theme.json at the theme root and reference the official schema so editors can validate and autocomplete it.

{ "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 3, "settings": {}, "styles": {} }

The snippets below show separate parts of one file; merge their settings objects rather than pasting several root objects into theme.json. The trunk schema helps during development, but production behavior depends on the WordPress versions you support. Test the oldest supported core release and avoid properties it does not understand unless the theme has a graceful fallback.

Define a constrained color palette

{ "settings": { "color": { "custom": false, "defaultPalette": false, "palette": [ { "slug": "brand", "color": "#2457d6", "name": "Brand" }, { "slug": "ink", "color": "#172033", "name": "Ink" }, { "slug": "surface", "color": "#f5f7fb", "name": "Surface" } ] } } }

WordPress produces classes such as has-brand-color and variables such as --wp--preset--color--brand. Use generated variables in custom CSS instead of repeating hex values. Disabling custom colors is a product decision: it improves consistency but may be inappropriate for sites where editors legitimately need a wider palette.

Create typography and spacing scales

{ "settings": { "typography": { "fluid": true, "fontSizes": [ { "slug": "small", "size": "0.875rem", "name": "Small" }, { "slug": "body", "size": "1rem", "name": "Body" }, { "slug": "display", "size": "clamp(2.25rem, 6vw, 4.5rem)", "name": "Display" } ] }, "spacing": { "units": [ "rem", "vw" ], "spacingSizes": [ { "slug": "20", "size": "0.5rem", "name": "2XS" }, { "slug": "40", "size": "1rem", "name": "S" }, { "slug": "60", "size": "2rem", "name": "L" } ] } } }

Keep scale slugs stable because templates and saved content can reference them. Names are editor-facing and can change; slugs act more like API identifiers.

Set layout tokens at the root

{ "settings": { "layout": { "contentSize": "42rem", "wideSize": "72rem" } } }

These values align core blocks, templates, and custom blocks around the same content geometry. Test nested constrained and flex layouts because parent blocks can change how child widths are interpreted.

Apply defaults without locking every block

The styles section defines global and block-specific defaults.

{ "styles": { "color": { "background": "var:preset|color|surface", "text": "var:preset|color|ink" }, "typography": { "fontSize": "var:preset|font-size|body", "lineHeight": "1.65" }, "blocks": { "core/button": { "border": { "radius": "0.35rem" }, "typography": { "fontWeight": "700" } } } } }

Use JSON presets and styles for editor-visible design decisions. Keep complex selectors, stateful interactions, browser workarounds, animations, and component logic in CSS. Forcing them into JSON usually reduces clarity.

Control the cascade intentionally

WordPress combines core, theme, and user origins. User choices normally win over theme defaults. Specific block styles can override root theme styles. Inspect generated global styles when a value seems ignored rather than escalating CSS specificity immediately.

Child themes and style variations add more layers. Document which values are brand invariants, which are theme defaults, and which editors may override. A design system without an ownership model turns into a specificity contest.

Test the editor as part of the product

  1. Open common templates and verify editor/front-end parity.
  2. Check palette contrast for text and interactive states.
  3. Test every spacing and type preset at narrow and wide viewports.
  4. Inspect existing content for removed preset slugs.
  5. Confirm custom blocks opt into the supports they actually handle.
  6. Verify the oldest supported WordPress version.

Removing a preset from the picker does not update saved content that references its slug. Keep a compatibility CSS variable or migrate affected blocks before deletion.

Version token changes in release notes that editors can understand. A renamed color or removed spacing step may look like an implementation detail, yet existing patterns, templates, and custom CSS can depend on its generated variable. Search the repository and stored block markup for the slug, supply a compatibility alias when practical, and schedule destructive cleanup separately. Design tokens are safer when consumers can see their lifecycle instead of discovering it through a broken layout.

Treat tokens as a maintained interface

A good theme.json reduces duplicated CSS, gives editors safer choices, and makes custom blocks feel native. Keep the token set small, name it semantically, preserve stable slugs, and review changes as you would an API. The official Global Settings and Styles documentation explains the hierarchy and available settings; your design audit determines which of them deserve to become site-wide contracts.

Photo by cottonbro studio on Pexels.

Adrian Saycon

Written by

Adrian Saycon

A developer with a passion for emerging technologies, Adrian Saycon focuses on transforming the latest tech trends into great, functional products.

Discussion (0)

Sign in to join the discussion

No comments yet. Be the first to share your thoughts.

Latest Articles

From the Blog

View all articles