Written by 6:03 am Theme Development Views: 1

WordPress theme.json Explained: Control Your Theme Without CSS

Learn how theme.json works – define color palettes, typography, spacing presets, and block styles from one central configuration file.

WordPress theme.json Explained: Control Your Theme Without CSS

theme.json is WordPress’s modern system for controlling your theme’s visual design without writing a single line of CSS. It defines colors, typography, spacing, and layout from one central file. Whether you’re building a block theme from scratch or adding Global Styles support to a classic theme, understanding theme.json fundamentally changes how you approach WordPress customization.


What Is theme.json and Why Does It Exist?

Before theme.json, every WordPress theme managed styles through multiple scattered locations: functions.php for adding theme support, style.css for CSS rules, add_theme_support() calls for editor color palettes, and separate editor-style.css for Gutenberg styling. This fragmented system made it easy for theme styles and editor styles to diverge, causing what you saw in the editor to look different from what published pages showed.

theme.json was introduced in WordPress 5.8 and became the backbone of the Full Site Editing (FSE) system. It provides a single source of truth for design decisions. Values defined in theme.json automatically apply to both the front end and the block editor – no more editor/frontend style mismatches.

The file lives at the root of your theme directory: wp-content/themes/your-theme/theme.json. For child themes, a theme.json in the child theme directory overrides specific values from the parent, letting you customize design tokens without duplicating the entire file.


The Structure of theme.json

A theme.json file is a JSON object with a specific structure. At its top level, the most important properties are version, settings, styles, and customTemplates.

The settings section defines what options are available – color palettes, typography scales, spacing presets, and which features blocks can use. The styles section applies actual values – setting the body background color, defining the base font size, controlling link colors. Think of settings as capabilities and styles as the applied design decisions.

A minimal valid theme.json looks like this structure (without using wp:code blocks): a JSON object with version set to 3 (current as of WordPress 6.5+), a settings object, and a styles object. The version number matters – different versions have different property support.


Defining Your Color Palette

One of the most powerful uses of theme.json is defining a color palette that appears in the Gutenberg block editor’s color picker. This ensures site editors only choose from your approved brand colors rather than entering arbitrary hex values.

Colors are defined under settings.color.palette as an array of objects. Each color object has three properties: slug (a machine-readable identifier), name (what appears in the editor), and color (the hex, RGB, or HSL value). The slug is important – WordPress generates CSS custom properties from it automatically, making the color available throughout your CSS as var(--wp--preset--color--your-slug).

For example, a color with slug “primary” becomes available in CSS as var(--wp--preset--color--primary). This means you can use theme.json colors in your custom CSS without hardcoding values, keeping everything in sync from the same source.

Disabling Core WordPress Color Palettes

By default, WordPress includes its own color palette alongside your custom one. To show only your brand colors, set settings.color.defaultPalette to false. This removes the WordPress default colors from the editor. Similarly, settings.color.defaultGradients: false removes default gradients, and settings.color.defaultDuotone: false removes default duotone filters.


Typography: Fonts, Sizes, and Font Families

theme.json handles typography through the settings.typography section. You can define font size scales, font families, and line height options that appear in the editor.

Font Size Presets

Font sizes are defined as an array under settings.typography.fontSizes. Each size has a slug, name, and size value. The size value can use any CSS unit including px, em, rem, and clamp() for fluid typography. A well-designed font size scale typically includes: small, medium (base), large, x-large, and xx-large. Each slug generates a CSS custom property: a slug of “large” creates var(--wp--preset--font-size--large).

Registering Font Families

Font families are defined under settings.typography.fontFamilies. For each font family, you specify the slug, name, and fontFamily (the CSS font-family value including fallbacks). For web fonts loaded from a font file, you also include a fontFace array that defines the @font-face rules – format, style, weight, and the file path relative to the theme’s fonts directory.

WordPress 6.5+ added the Global Fonts (formerly Font Library) system in the editor, which complements theme.json font registration by letting site administrators install fonts from the dashboard. Theme-defined fonts in theme.json always take precedence and are bundled with your theme.


Spacing and Layout Controls

theme.json’s spacing system solves one of the most inconsistent areas of WordPress theme development: padding, margin, and gap values. The settings.spacing section lets you define spacing presets and enable padding/margin controls on blocks.

Spacing Presets

Spacing presets work like color and font size presets – define an array of values with slugs that generate CSS custom properties. A standard spacing scale might range from very small (4px) to extra large (96px), creating a consistent visual rhythm across your site.

Set settings.spacing.defaultSpacingSizes: false to hide WordPress’s default spacing scale and show only yours. This prevents editors from choosing spacing values outside your design system.

Content Width and Wide Width

The settings.layout section controls two critical width values: contentSize and wideSize. Content size is the default maximum width of your content area – typically 680px to 800px for readable prose. Wide size is the maximum width for blocks set to “Wide” alignment – typically 1200px to 1400px. These values determine what “Align Wide” and “Align Full” mean for each block in the editor.


Applying Styles: The styles Section

While settings defines what’s available, the styles section applies design values to elements and blocks. This is where you set your actual font choices, colors, and spacing – using the custom properties generated from your presets for consistency.

Global Element Styles

Under styles.elements, you can style HTML elements across the entire site: headings (h1-h6), links (with hover and focus states), buttons, captions. For each element, you can set color (text and background), typography (font family, size, style, weight), and spacing properties.

For link styling, theme.json supports pseudo-class targeting via the :hover key inside the element definition – this means you can set link hover colors without writing any CSS. The same applies to button hover states.

Block-Level Styles

Under styles.blocks, you can set default styles for specific blocks. For example, you can set the default font size for core/paragraph blocks, the default alignment for core/image blocks, or the background color for core/pullquote blocks. These act as sensible defaults that site editors can override per-block.


Feature Controls: What You Can Turn On and Off

theme.json gives you fine-grained control over which editing capabilities are available in the block editor. This is valuable for client sites where you want to limit options to prevent design chaos.

Featuretheme.json SettingEffect When Disabled
Custom colorssettings.color.custom: falseRemoves freeform color input, palette only
Custom font sizessettings.typography.customFontSize: falseFont size scale only, no manual entry
Drop capssettings.typography.dropCap: falseRemoves drop cap option from paragraphs
Block paddingsettings.spacing.padding: falseRemoves padding controls from blocks
Appearance toolssettings.appearanceTools: trueEnables color, typography, spacing controls

Setting settings.appearanceTools: true is a shorthand that enables the full suite of typography, spacing, border, color, and dimensions controls across all blocks. This is often the fastest way to get a feature-complete editing experience without configuring each individual setting.


Using theme.json in a Child Theme

If you’re working with an existing block theme and want to customize its design tokens without modifying the parent theme files, create a theme.json in your child theme directory. Child theme.json values are merged with the parent’s, with child values taking precedence. You only need to include the specific values you want to override – you don’t need to duplicate the entire parent file.

For example, to override just the primary color from a parent block theme, create a theme.json in your child theme that contains only the settings.color.palette array with your replacement colors. WordPress merges this with the parent’s full theme.json at runtime.


Practical Example: Building a Brand Color System

To illustrate how theme.json connects settings to styles to CSS, here’s the logical flow for implementing a brand color system: You define four colors in settings.color.palette with slugs “brand-primary”, “brand-secondary”, “text-dark”, and “background-light”. WordPress automatically generates CSS custom properties for each. You then reference those custom properties in styles.elements.link.color.text using the preset reference format. The editor’s color picker shows exactly these four colors. A site editor clicking a link color in the editor and choosing “Brand Primary” applies the same value that appears on the front end. One source of truth.

theme.json does not replace CSS – it creates a design token layer above CSS that keeps your editor and frontend in sync automatically.


Common Mistakes and How to Avoid Them

  • Wrong version number: Always set the version field. Using version 2 in a WordPress 6.5+ site misses out on new features. Use version 3 for current WordPress versions.
  • Forgetting JSON syntax: theme.json must be valid JSON. Trailing commas, missing quotation marks, and mismatched braces will silently break the file with no helpful error message. Validate your JSON at jsonlint.com before uploading.
  • Using block names without checking them: Block name slugs in styles.blocks must match the registered block name exactly (e.g., core/paragraph, not paragraph). Wrong block names are silently ignored.
  • Overriding too much from a parent theme: If you define a complete color palette in a child theme.json, it replaces the parent’s palette entirely, not merges. Be specific about what you override.

Advanced theme.json Techniques

Once you understand the basics of theme.json, several advanced patterns unlock additional control over the editing experience and output quality of your WordPress theme.

Locking Down the Editor for Clients

The settings.appearanceTools property in theme.json controls whether users see design tools in the block editor. Setting "appearanceTools": false hides color pickers, typography controls, and spacing tools from the editing interface entirely. This is useful when you want clients to work with predefined design options only. You can be more granular: "settings.color.text": false hides text color controls specifically while leaving other controls accessible. Combining these restrictions with a curated palette and preset typography creates a controlled editing environment that prevents brand inconsistency.

Using theme.json Presets in CSS

WordPress generates CSS custom properties from your theme.json palette and typography definitions. A color defined as “primary” in your palette becomes --wp--preset--color--primary in the generated CSS. A font size defined as “large” becomes --wp--preset--font-size--large. You can reference these custom properties in your custom CSS to stay in sync with your design tokens without hardcoding values. If you later change a color in theme.json, every place in your CSS that references the custom property updates automatically.

Child Themes and theme.json Inheritance

A child theme can include its own theme.json file to extend or override the parent theme’s settings. The merge behavior follows specific rules: scalar values (like color hex values) override the parent, while arrays (like palette arrays) replace the parent array entirely rather than merging item by item. This means if your child theme.json defines a color palette with three colors, you replace the parent’s entire palette with those three colors – you don’t add your three colors to the parent’s existing palette. To add colors while keeping the parent’s palette, you must include the parent’s colors in your child theme.json array alongside your additions.


Common Questions About theme.json

Does theme.json work with classic themes?

theme.json was introduced for block themes but classic themes can also include a theme.json file starting with WordPress 5.8. However, classic themes only benefit from a subset of theme.json features. Color palettes, gradient presets, and font size presets defined in theme.json will appear in the block editor for any blocks you use. The Global Styles interface in the Site Editor is only available for block themes. If you are using a classic theme, the main benefit of adding theme.json is providing curated presets that appear in the editor color and typography pickers.

How do I find the correct version number for theme.json?

The version field in theme.json must match the schema version supported by your WordPress installation. As of WordPress 6.5+, version 3 is current. Older WordPress installations support version 2. If you are building for current WordPress (6.x), use version 3. The differences between versions affect which properties are available and how inheritance works. Always check the WordPress Developer Handbook or the Gutenberg repository changelog when a new WordPress major version ships to see if a new theme.json schema version was introduced.

Next Steps with theme.json

Start with the Global Styles interface in the block editor (Appearance → Editor → Styles) to visually understand what theme.json controls. Changes made in the editor’s Global Styles panel are stored as a user customization layer on top of theme.json. Export these changes to understand the JSON structure before writing it manually.

For more on building with the block editor, see our guide on creating a WordPress child theme without breaking your parent theme. For a strong foundation before diving into theme.json, our guide to choosing the right WordPress theme helps you pick a well-built starting point.

Visited 1 times, 1 visit(s) today

Last modified: April 6, 2026

Close