Blog Reference
theme.json colour presets, and why a pattern should never state a hex
How WordPress turns a palette in theme.json into CSS custom properties, what breaks when a pattern hardcodes a colour, and the fallback chain that fixes it.
WordPress turns palette arrays in theme.json into CSS custom properties on the root element. When block patterns reference those palette slugs, pasted sections inherit active brand colours immediately. When patterns write raw hex values into block attributes, they inject inline styles that bypass the theme's design system entirely.
How WordPress compiles palette presets#
A colour palette declared in theme.json defines named slugs and hex defaults:
{
"version": 3,
"settings": {
"color": {
"palette": [
{ "slug": "primary", "color": "#1f3a93", "name": "Primary" },
{ "slug": "base", "color": "#ffffff", "name": "Base" },
{ "slug": "contrast", "color": "#111111", "name": "Contrast" }
]
}
}
}
On render, WordPress generates CSS custom properties on the :root element:
:root {
--wp--preset--color--primary: #1f3a93;
--wp--preset--color--base: #ffffff;
--wp--preset--color--contrast: #111111;
}
WordPress also generates utility classes: .has-primary-color, .has-primary-background-color, and equivalents for each registered slug.
When you select a palette colour in the block inspector, WordPress saves the slug attribute to the block comment (e.g. "backgroundColor":"primary"). The browser resolves the CSS custom property at runtime. If you update #1f3a93 to #104f55 in theme.json, every block referencing primary updates without touching post records.
How third-party patterns break theme palettes#
External block patterns commonly introduce colour debt in three ways:
1. Hardcoded inline styles#
Many pattern exporters serialise explicit hex values into the block style object:
<!-- wp:group {"style":{"color":{"background":"#0f1430"}}} -->
Inline styles override utility classes and theme custom properties on that specific element. If a site uses an olive and cream palette, a pasted section with hardcoded navy retains its navy background until manually edited in the code editor.
2. Missing theme tokens#
Patterns configured against specific themes often reference non-standard slugs like accent-3 or tertiary. In a theme that only declares primary, base, and contrast, the generated CSS becomes:
color: var(--wp--preset--color--accent-3);
Because --wp--preset--color--accent-3 is undefined, the browser falls back to the inherited text colour. In dark sections, this frequently leads to dark text rendering over dark backgrounds without throwing a validation error.
3. Inconsistent slug naming across themes#
Across standard themes like Twenty Twenty-Five and Twenty Twenty-Four, only two slugs are universally present: base (background) and contrast (foreground). Theme developers use divergent names for brand colours (primary, accent, brand, vivid-cyan-blue).
Resilient CSS fallback chains#
To author patterns that remain legible across different block themes, use nested var() fallback chains in style declarations:
color: var(--wp--preset--color--primary,
var(--wp--preset--color--contrast,
#111111));
This fallback cascade resolves in three tiers:
- Target theme token: The preferred brand token (e.g.
primary). - Standard theme fallback: A universal token defined by virtually all block themes (
contrastorbase). - Static hex fallback: A neutral default ensuring legibility if custom properties fail entirely.
In block markup, write the fallback chain directly into the block style attribute:
<!-- wp:paragraph {"style":{"color":{"text":"var(--wp--preset--color--primary, var(--wp--preset--color--contrast, #111111))"}}} -->
Maintaining contrast across unknown palettes#
Fallback chains prevent undefined CSS, but accessible contrast requires deliberate token choices. If an accent fallback resolves to a light yellow in one theme and a deep violet in another, legibility shifts:
- Anchor body text to base and contrast tokens: Use
contrastfor dark text on light backgrounds andbasefor light text on dark backgrounds. Avoid mapping paragraph text to volatile accent slugs. - Audit across default themes: Before deploying custom patterns, test the markup across multiple default themes to verify WCAG AA contrast compliance.
Auditing theme colours in the browser#
To check colour declarations on an active site:
- Open DevTools, inspect the
<html>element, and verify the--wp--preset--color--*variables declared under:root. - Search
post_contentin your database for#characters inside block markup to locate hardcoded inline overrides. - Switch between block themes in development to confirm that pasted layouts inherit new palettes cleanly.
Every Pattern Paste pattern is built to respect theme design tokens, combining 232 patterns with clean fallbacks. Learn more about how the library works or explore the pattern catalogue.
Read next
- Why does my WordPress block pattern look different from the demo?Find out which differences come from your WordPress theme, which reveal a broken pattern, and what to check before adding another CSS override.6 September 2026
- Where block patterns come from, and what each source leaves in your pageThe pattern directory, your theme, a library plugin or a copy-paste catalogue: what each source puts in post_content, and what survives when it goes away.31 August 2026