What Is Theme JSON File in WordPress and How to Use It
Modern WordPress development is shifting away from scattered theme options and complex customizer settings toward a single, centralized configuration file. That file is the theme.json. If...
Modern WordPress development is shifting away from scattered theme options and complex customizer settings toward a single, centralized configuration file. That file is the theme.json. If you are building block themes or want tighter control over global styles and editor behavior, understanding how this file works is no longer optional—it’s essential.
What the theme.json File Does in WordPress
The theme.json file is a configuration file that lets theme authors define global styles and settings for both the front end and the block editor. Instead of registering settings in PHP and styling everything with CSS alone, you can declare your theme’s design system in a structured JSON format.
In practice, this file controls:
- Global styles (colors, typography, spacing, borders, etc.)
- Block-level styles (settings per block type)
- Editor features (which controls are available or disabled in the block editor)
- Presets (color palette, gradients, font sizes)
WordPress then uses this configuration to generate CSS and apply it consistently across your site and the editor. This ensures that what you see in the editor closely matches the front-end output while keeping your codebase organized and maintainable.
Where the theme.json File Lives
The file must be located at the root of your theme directory:
wp-content/themes/your-theme/theme.json
If WordPress detects this file, it treats the theme as a block-theme-aware theme and begins using your configuration for global styles and settings. Classic themes can also use it to participate in the global styles system even if they don’t use full-site editing templates.
Basic Structure of theme.json
The theme.json file follows a predictable structure with two major sections:
settings– Controls what is available in the editor (e.g., color palette, typography controls, spacing options).styles– Defines how elements and blocks look by default (e.g., link color, font family, block-specific styles).
A very minimal example looks like this:
{
"version": 2,
"settings": {
"color": {
"palette": [
{
"slug": "primary",
"name": "Primary",
"color": "#1a73e8"
}
]
}
},
"styles": {
"typography": {
"fontFamily": "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
}
}
}
The version key tells WordPress which schema to use. Make sure it matches the version supported by your target WordPress installation (currently 2 is the standard for modern themes).
Global Settings: Controlling What the Editor Offers
The settings section determines what kind of design options are available to users in the block editor. This is where you define your theme’s design tokens and constraints.
Color Settings and Palettes
You can provide a custom color palette and turn certain color features on or off. This helps enforce branding guidelines and avoids inconsistent color choices.
{
"settings": {
"color": {
"palette": [
{
"slug": "primary",
"name": "Primary",
"color": "#1a73e8"
},
{
"slug": "secondary",
"name": "Secondary",
"color": "#185abc"
},
{
"slug": "accent",
"name": "Accent",
"color": "#ffb300"
}
],
"gradients": [
{
"slug": "primary-gradient",
"name": "Primary Gradient",
"gradient": "linear-gradient(135deg, #1a73e8 0%, #185abc 100%)"
}
],
"custom": false,
"customGradient": false
}
}
}
In this example:
palettedefines brand colors used in the editor’s color picker.gradientsdefines reusable gradient presets.customandcustomGradientset tofalselock users to the provided palette and gradients for a more consistent design.
Typography Settings
Typography settings let you define font families, sizes, and whether users can add custom sizes.
{
"settings": {
"typography": {
"fontFamilies": [
{
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
"slug": "system",
"name": "System Default"
},
{
"fontFamily": "'Source Sans Pro', sans-serif",
"slug": "source-sans",
"name": "Source Sans Pro"
}
],
"fontSizes": [
{
"slug": "small",
"name": "Small",
"size": "14px"
},
{
"slug": "normal",
"name": "Normal",
"size": "16px"
},
{
"slug": "large",
"name": "Large",
"size": "20px"
},
{
"slug": "xl",
"name": "Extra Large",
"size": "32px"
}
],
"customFontSize": false,
"lineHeight": true
}
}
}
This gives the editor a curated set of fonts and font sizes while disabling arbitrary font sizes. The lineHeight option enables line-height controls in the editor where supported.
Spacing, Layout, and Other Controls
Spacing and layout configuration is vital for ensuring consistent padding, margins, and content widths.
{
"settings": {
"spacing": {
"padding": true,
"margin": true,
"units": [ "px", "em", "rem", "vw", "vh" ],
"spacingScale": {
"steps": 5,
"mediumStep": 1.5
}
},
"layout": {
"contentSize": "720px",
"wideSize": "1120px"
},
"border": {
"radius": true,
"color": true,
"style": true,
"width": true
}
}
}
Key ideas:
spacingcontrols whether users can adjust padding and margin and which units they can use.layoutdefines the content width and wide-alignment width for blocks like images and columns.borderenables UI controls for radius, color, style, and width when supported by blocks.
Global Styles: How Your Site Looks by Default
While settings control what users are allowed to change, the styles section controls the default look and feel. This includes base styles for the whole site and specific styles for HTML elements and individual blocks.
Base Styles for the Entire Site
You can define global defaults for typography, colors, and more:
{
"styles": {
"color": {
"background": "#ffffff",
"text": "#111111"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--system)",
"fontSize": "16px",
"lineHeight": "1.6"
},
"spacing": {
"blockGap": "1.5rem"
}
}
}
Here:
color.backgroundandcolor.textset the default site-wide colors.typographysets the body font, base size, and line height.spacing.blockGapdefines the default gap between blocks.
Styling HTML Elements (e.g., Headings, Links)
You can target HTML elements via the elements subkey:
{
"styles": {
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--primary)"
},
"typography": {
"textDecoration": "none"
}
},
"heading": {
"typography": {
"fontFamily": "var(--wp--preset--font-family--source-sans)",
"fontWeight": "700"
},
"color": {
"text": "#111111"
}
},
"h1": {
"typography": {
"fontSize": "36px"
}
},
"h2": {
"typography": {
"fontSize": "30px"
}
}
}
}
}
This allows you to define shared rules for all headings via heading, plus specific overrides for each heading level like h1 and h2. The link element targets anchor tags globally.
Block-Specific Styles
One of the strengths of theme.json is that you can define default styles per block type. This reduces the amount of custom CSS and makes your theme behavior more predictable.
{
"styles": {
"blocks": {
"core/paragraph": {
"typography": {
"fontSize": "18px"
}
},
"core/heading": {
"spacing": {
"margin": {
"bottom": "1.2em"
}
}
},
"core/button": {
"color": {
"background": "var(--wp--preset--color--primary)",
"text": "#ffffff"
},
"border": {
"radius": "4px"
},
"typography": {
"fontWeight": "600",
"textTransform": "uppercase"
}
}
}
}
}
This example:
- Increases the default paragraph size.
- Adds consistent bottom margins to headings.
- Defines button colors, radius, and text styling for
core/button.
These styles are applied both in the editor and on the front end, ensuring WYSIWYG consistency for block-based themes.
Combining Settings and Styles: A Practical Example
To see everything in context, here is a condensed example of a theme.json that configures a simple, opinionated design system.
{
"version": 2,
"settings": {
"color": {
"palette": [
{ "slug": "primary", "name": "Primary", "color": "#1a73e8" },
{ "slug": "secondary", "name": "Secondary", "color": "#185abc" },
{ "slug": "accent", "name": "Accent", "color": "#ffb300" },
{ "slug": "dark", "name": "Dark", "color": "#111111" },
{ "slug": "light", "name": "Light", "color": "#f5f5f5" }
],
"custom": false
},
"typography": {
"fontFamilies": [
{
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
"slug": "system",
"name": "System Default"
},
{
"fontFamily": "'Source Sans Pro', sans-serif",
"slug": "source-sans",
"name": "Source Sans Pro"
}
],
"fontSizes": [
{ "slug": "small", "name": "Small", "size": "14px" },
{ "slug": "normal", "name": "Normal", "size": "16px" },
{ "slug": "medium", "name": "Medium", "size": "18px" },
{ "slug": "large", "name": "Large", "size": "24px" },
{ "slug": "xl", "name": "Extra Large", "size": "32px" }
],
"customFontSize": false,
"lineHeight": true
},
"spacing": {
"padding": true,
"margin": true,
"units": [ "px", "em", "rem" ]
},
"layout": {
"contentSize": "720px",
"wideSize": "1120px"
},
"border": {
"radius": true,
"width": true
}
},
"styles": {
"color": {
"background": "#ffffff",
"text": "#111111"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--source-sans)",
"fontSize": "16px",
"lineHeight": "1.7"
},
"spacing": {
"blockGap": "1.5rem"
},
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--primary)"
},
"typography": {
"textDecoration": "none"
}
},
"heading": {
"color": {
"text": "#111111"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--system)",
"fontWeight": "700",
"lineHeight": "1.3"
}
}
},
"blocks": {
"core/paragraph": {
"typography": {
"fontSize": "18px"
}
},
"core/heading": {
"spacing": {
"margin": {
"bottom": "1.2em"
}
}
},
"core/button": {
"color": {
"background": "var(--wp--preset--color--primary)",
"text": "#ffffff"
},
"border": {
"radius": "4px"
},
"spacing": {
"padding": {
"top": "0.7em",
"right": "1.4em",
"bottom": "0.7em",
"left": "1.4em"
}
},
"typography": {
"fontWeight": "600",
"textTransform": "uppercase"
}
},
"core/separator": {
"color": {
"background": "var(--wp--preset--color--light)"
}
}
}
}
}
This configuration gives you:
- A locked-in color palette aligned with your brand.
- Predefined typography scales and font families.
- Consistent spacing and layout values.
- Block defaults that keep the editor output visually cohesive.
How theme.json Affects Performance and Maintainability
Using a theme.json file has direct benefits beyond editor experience. It can help with performance and long-term maintainability of your theme.
Less Custom CSS and Fewer Overrides
By delegating styles to the global styles engine, you can significantly reduce your custom CSS file size. You no longer need to write large CSS rules for core blocks; instead, you rely on block-level styles in JSON that WordPress translates into efficient stylesheets.
This also minimizes specificity wars and the need for awkward !important rules. Since styles are generated from a single configuration, they are easier to trace and adjust.
Editor-Front End Parity
One of the most common complaints about older WordPress workflows was that the editor never quite matched the front end. With theme.json, the same design tokens and styles are used for both, which improves confidence for content creators and reduces surprises when publishing.
Improved Core Integration and Future-Proofing
WordPress core continues to evolve around the global styles architecture. Themes that adopt theme.json are better positioned to benefit from future enhancements, new block features, and improvements in the site editor without major rewrites.
Editor Features You Can Control via theme.json
Beyond visuals, the configuration file can also enable or disable specific editor features to match your design requirements.
- Control availability of custom colors and gradients by toggling
customandcustomGradient. - Enable or disable duotone filters for images and media.
- Limit spacing controls to certain units or disable them entirely.
- Turn off custom font sizes to enforce a strict typographic scale.
These constraints are especially valuable in client work, where you want to give content editors flexibility but still protect the design integrity of the site.
Working with theme.json in Child Themes
If you are building a child theme for an existing block theme, you can provide your own theme.json to override or extend the parent’s configuration. WordPress merges the parent and child files, with the child taking precedence for overlapping
I’ve been leading Grafiduo since 2010 as the CEO. Together with my development team, I create e-commerce solutions, websites, and digital designs that combine functionality with aesthetics. I focus mainly on WordPress, WooCommerce, and Prestashop, helping businesses grow through well-crafted online experiences.