theme.json Schema Overview

The theme.json file is WordPress’s unified configuration system for block themes, controlling global styles, editor settings, and theme behavior.

File Location

theme-root/
├── theme.json           # Theme configuration
├── styles/              # Optional style variations
│   ├── dark.json
│   └── contrast.json
└── ...

Schema Version

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

Version History

VersionWordPressKey Changes
15.8Initial release
25.9Added appearanceTools, renamed settings.border.customColorsettings.border.color
36.6Changed settings.typography.defaultFontSizes default to true, added settings.background.backgroundSize

Always use version 3 for new themes. WordPress auto-migrates older versions.

Top-Level Structure

json
{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "title": "Theme Name",
  "description": "Theme description for style variations",
  "settings": { },
  "styles": { },
  "customTemplates": [ ],
  "templateParts": [ ],
  "patterns": [ ]
}

Property Summary

PropertyTypePurpose
$schemastringJSON schema URL for IDE validation
versionintegerSchema version (1, 2, or 3)
titlestringDisplay name (used in style variations)
descriptionstringDescription (used in style variations)
settingsobjectEditor features and design tokens
stylesobjectCSS styling rules
customTemplatesarrayCustom template definitions
templatePartsarrayTemplate part definitions
patternsarrayPattern slugs to register

Inheritance Chain

WordPress merges theme.json from multiple sources in this order (later overrides earlier):

1. WordPress Core Defaults
        ↓
2. Theme's theme.json
        ↓
3. Child Theme's theme.json (if applicable)
        ↓
4. User Customizations (stored in database)

Core Defaults Location

WordPress core defaults are defined in:

wp-includes/theme.json

How Merging Works

Settings: Deep merged. Theme values override core, user overrides theme.

// Core default
{ "settings": { "color": { "defaultPalette": true } } }

// Theme overrides
{ "settings": { "color": { "defaultPalette": false, "palette": [...] } } }

// Result: defaultPalette is false, palette from theme, other color settings from core

Styles: Deep merged at each level.

// Theme
{ "styles": { "color": { "background": "#fff" } } }

// User customization
{ "styles": { "color": { "text": "#000" } } }

// Result: both background and text are applied

Arrays (palette, fontSizes, etc.): Theme arrays replace core arrays entirely, not merge.

// Core has 12 default colors
// Theme defines 5 colors
// Result: Only 5 theme colors available (core colors removed)

Accessing Merged Configuration

PHP

php
// Get complete merged settings
$settings = wp_get_global_settings();

// Get specific setting
$palette = wp_get_global_settings( array( 'color', 'palette' ) );

// Get complete merged styles
$styles = wp_get_global_styles();

// Get specific style
$background = wp_get_global_styles( array( 'color', 'background' ) );

JavaScript (Block Editor)

javascript
import { useSettings, useSetting } from '@wordpress/block-editor';

// Get multiple settings
const [ fontSizes, colors ] = useSettings( 'typography.fontSizes', 'color.palette' );

// Get single setting
const palette = useSetting( 'color.palette' );

Context: Global vs Block-Level

Both settings and styles can be defined globally or per-block:

json
{
  "settings": {
    "color": {
      "palette": [ /* global palette */ ]
    },
    "blocks": {
      "core/paragraph": {
        "color": {
          "palette": [ /* paragraph-only palette */ ]
        }
      }
    }
  },
  "styles": {
    "color": {
      "background": "#ffffff"
    },
    "blocks": {
      "core/paragraph": {
        "color": {
          "text": "#333333"
        }
      }
    }
  }
}

Block-level settings/styles override global ones for that specific block.

Minimal Valid theme.json

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

This uses all WordPress defaults.

Complete Example

json
{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "title": "My Theme",
  "settings": {
    "appearanceTools": true,
    "color": {
      "palette": [
        { "slug": "primary", "color": "#0066cc", "name": "Primary" },
        { "slug": "secondary", "color": "#333333", "name": "Secondary" }
      ]
    },
    "typography": {
      "fontFamilies": [
        {
          "slug": "system",
          "name": "System Font",
          "fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
        }
      ]
    },
    "layout": {
      "contentSize": "650px",
      "wideSize": "1200px"
    }
  },
  "styles": {
    "color": {
      "background": "var(--wp--preset--color--primary)",
      "text": "#ffffff"
    },
    "typography": {
      "fontFamily": "var(--wp--preset--font-family--system)",
      "fontSize": "1rem",
      "lineHeight": "1.6"
    },
    "elements": {
      "link": {
        "color": { "text": "#ffffff" },
        ":hover": { "color": { "text": "#cccccc" } }
      }
    }
  },
  "templateParts": [
    { "name": "header", "area": "header", "title": "Header" },
    { "name": "footer", "area": "footer", "title": "Footer" }
  ],
  "customTemplates": [
    { "name": "blank", "title": "Blank", "postTypes": ["page", "post"] }
  ],
  "patterns": [ "theme-slug/hero", "theme-slug/cta" ]
}