Theme.json

theme.json is a configuration file used in block themes to define global settings, styles, and design systems for both the editor and frontend.

It acts as a central source of truth for:

  • Design tokens (colors, typography, spacing)
  • Editor capabilities
  • Block-level customization

How to Create theme.json

Create a theme.json file in the root of your theme:

my-block-theme/
├── theme.json

Minimal Example

{
  "version": 2,
  "settings": {},
  "styles": {}
}

Settings and Styles

settings

Defines what tools and options are available in the editor.

Example: Color, Typography, Spacing

{
  "settings": {
    "color": {
      "palette": [
        {
          "name": "Primary",
          "slug": "primary",
          "color": "#0073aa"
        }
      ],
      "custom": false
    },
    "typography": {
      "fontSizes": [
        {
          "name": "Medium",
          "slug": "medium",
          "size": "18px"
        }
      ],
      "customFontSize": false
    },
    "spacing": {
      "units": [ "px", "em", "rem" ]
    }
  }
}

Enabling/Disabling Features

{
  "settings": {
    "color": {
      "custom": false
    },
    "typography": {
      "customLineHeight": false
    }
  }
}

styles

Defines actual visual styles applied globally or per block.

Global Styles Example

{
  "styles": {
    "color": {
      "background": "#ffffff",
      "text": "#000000"
    },
    "typography": {
      "fontFamily": "Arial, sans-serif",
      "lineHeight": "1.6"
    },
    "spacing": {
      "padding": "20px"
    }
  }
}

Block-Level Styles

{
  "styles": {
    "blocks": {
      "core/button": {
        "color": {
          "background": "#0073aa",
          "text": "#ffffff"
        }
      }
    }
  }
}

Layout Configuration

Control content width and alignment:

{
  "settings": {
    "layout": {
      "contentSize": "700px",
      "wideSize": "1200px"
    }
  }
}

Assigning Template Parts

Template parts can be declared in theme.json for better organization.

{
  "templateParts": [
    {
      "name": "header",
      "title": "Header",
      "area": "header"
    },
    {
      "name": "footer",
      "title": "Footer",
      "area": "footer"
    }
  ]
}

Defining Custom Templates

You can define custom templates available in the editor.

{
  "customTemplates": [
    {
      "name": "landing-page",
      "title": "Landing Page",
      "postTypes": [ "page" ]
    }
  ]
}

Global Style Variations

Block themes can include multiple style variations using additional JSON files.

Folder Structure

styles/
├── dark.json
├── light.json

Example: styles/dark.json

{
  "version": 2,
  "styles": {
    "color": {
      "background": "#000000",
      "text": "#ffffff"
    }
  }
}

Behavior

  • Users can select styles from the Site Editor
  • Selected variation overrides the default theme.json

Important Notes

  • Settings in theme.json can replace add_theme_support()
  • theme.json has higher priority than PHP-based theme supports
  • Encourages standardization (color slugs, font sizes, spacing)
  • Supports modern features like fluid typography

When to Use CSS vs theme.json

Use theme.json for:

  • Global design system
  • Block styling
  • Editor configuration

Use CSS for:

  • Complex selectors
  • Animations
  • Advanced layouts not supported in schema

Internationalization in Block Themes

What is Internationalization (i18n)?

Internationalization is the process of making a theme translatable into multiple languages.


Key Challenge in Block Themes

  • Templates are HTML files
  • PHP functions like __() cannot be used directly
  • Static text cannot be dynamically translated in templates

Use Block Patterns for Translatable Content

Convert static template content into patterns, where translation can be handled properly.

Example Pattern Registration

function my_theme_register_patterns() {
    register_block_pattern(
        'my-theme/hero',
        [
            'title'   => __( 'Hero Section', 'my-theme' ),
            'content' => '
                <!-- wp:heading -->
                <h2>' . esc_html__( 'Welcome to our site', 'my-theme' ) . '</h2>
                <!-- /wp:heading -->
            ',
        ]
    );
}
add_action( 'init', 'my_theme_register_patterns' );

Use JavaScript i18n for Blocks

For dynamic or custom blocks:

import { __ } from '@wordpress/i18n';

const title = __( 'Read More', 'my-theme' );

Handling Images Dynamically

Since templates cannot use PHP:

  • Use patterns or blocks
  • Use get_theme_file_uri() inside PHP when registering patterns

Creating a POT File

Generate translation files using WP-CLI:

wp i18n make-pot . languages/my-theme.pot

Best Practices

  • Always define a text domain
  • Avoid hardcoded text in templates
  • Prefer patterns or dynamic blocks for translatable content
  • Keep translation strings in PHP or JS
  • Ensure consistency across theme files