The theme.json file is the single most important configuration file in modern WordPress block theme development. Introduced in WordPress 5.8 and refined through every subsequent release, theme.json gives developers centralized control over global styles, block settings, typography, colors, spacing, and layout — all without writing a single line of CSS. If you are building block themes in 2026, mastering theme.json is not optional. It is foundational.
This guide covers everything you need to know about theme.json: its file structure, schema versions, every major settings section, the styles system, custom templates, template parts, and practical patterns you can use in production block themes. Every example references the official WordPress developer documentation so you can verify and extend what you learn here.
What Is theme.json and Why Does It Matter?
Before theme.json existed, WordPress theme developers relied on a fragmented system of add_theme_support() calls in functions.php, custom CSS files, and Customizer settings to control how a theme looked and behaved. Colors lived in one place. Typography lived in another. Spacing was controlled through stylesheets. There was no unified API.
theme.json changed all of that. As Rich Tabor, one of the early advocates of Full Site Editing, put it: “theme.json is the bridge between theme developers and the block editor. It lets you define your design system in one place, and WordPress applies it everywhere.”
The file sits in your theme’s root directory and serves three primary purposes:
- Settings — Define which design tools are available in the editor (color palettes, font families, spacing presets, layout widths)
- Styles — Apply default visual styles globally and per-block (background colors, typography, padding, margins)
- Custom Templates and Template Parts — Register custom page templates and reusable template parts that appear in the Site Editor
WordPress reads theme.json during page load and generates the appropriate CSS custom properties and inline styles automatically. This means you get consistent styling across the editor and the front end without maintaining duplicate stylesheets.
Schema Versions: Understanding the Version Property
Every theme.json file must declare a version property at the top level. This tells WordPress which schema to use when parsing the file. As of WordPress 6.6+, there are three schema versions:
| Version | WordPress Release | Key Changes |
|---|---|---|
1 | 5.8 | Initial release. Basic settings and styles support. |
2 | 5.9 | Restructured settings/styles hierarchy. Added appearanceTools, layout, custom spacing scale. Current standard. |
3 | 6.6 | Added defaultFontSizes override, revised typography fluid settings, improved block-level granularity. |
Always use the latest version your minimum supported WordPress version allows. For most themes targeting WordPress 6.0+, version 2 is the standard. If you target 6.6+, version 3 unlocks additional typography controls.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3
}
The $schema property is optional but highly recommended. It enables autocompletion and validation in code editors like VS Code, catching errors before you even load your theme. Point it to https://schemas.wp.org/trunk/theme.json for the latest schema, or pin it to a specific WordPress version like https://schemas.wp.org/wp/6.6/theme.json.
The Settings Section: Controlling the Editor Experience
The settings object is where you define what design tools are available to content creators in the block editor. Think of it as your theme’s design system API. You are not applying styles here — you are defining the palette of options that users can choose from.
Color Settings
Color is often the first thing developers configure. You can define a custom color palette, gradient presets, and control which color features are exposed in the editor.
{
"version": 3,
"settings": {
"color": {
"custom": true,
"customGradient": true,
"defaultPalette": false,
"defaultGradients": false,
"palette": [
{
"slug": "primary",
"color": "#1e3a5f",
"name": "Primary Blue"
},
{
"slug": "secondary",
"color": "#f0c040",
"name": "Secondary Gold"
},
{
"slug": "neutral-light",
"color": "#f5f5f5",
"name": "Light Gray"
},
{
"slug": "neutral-dark",
"color": "#1a1a1a",
"name": "Dark"
}
],
"gradients": [
{
"slug": "primary-to-dark",
"gradient": "linear-gradient(135deg, #1e3a5f 0%, #1a1a1a 100%)",
"name": "Primary to Dark"
}
]
}
}
}
Setting defaultPalette to false removes WordPress’s built-in color palette, ensuring users only see your curated brand colors. Each palette entry generates a CSS custom property: --wp--preset--color--primary, --wp--preset--color--secondary, and so on. These are available throughout your theme and in the editor.
Typography Settings
Typography in theme.json covers font families, font sizes, line height, letter spacing, text decoration, text transform, and font weight controls. This is one of the most powerful sections because it lets you build a complete type scale.
{
"settings": {
"typography": {
"fluid": true,
"fontFamilies": [
{
"fontFamily": "'Inter', sans-serif",
"slug": "body-font",
"name": "Inter",
"fontFace": [
{
"fontFamily": "Inter",
"fontWeight": "400 700",
"fontStyle": "normal",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/inter-variable.woff2"]
}
]
},
{
"fontFamily": "'JetBrains Mono', monospace",
"slug": "code-font",
"name": "JetBrains Mono",
"fontFace": [
{
"fontFamily": "JetBrains Mono",
"fontWeight": "400",
"fontStyle": "normal",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/jetbrains-mono-regular.woff2"]
}
]
}
],
"fontSizes": [
{ "slug": "small", "size": "0.875rem", "name": "Small", "fluid": { "min": "0.813rem", "max": "0.875rem" } },
{ "slug": "medium", "size": "1rem", "name": "Medium", "fluid": { "min": "0.938rem", "max": "1rem" } },
{ "slug": "large", "size": "1.25rem", "name": "Large", "fluid": { "min": "1.125rem", "max": "1.25rem" } },
{ "slug": "x-large", "size": "1.75rem", "name": "Extra Large", "fluid": { "min": "1.5rem", "max": "1.75rem" } },
{ "slug": "xx-large", "size": "2.5rem", "name": "Huge", "fluid": { "min": "2rem", "max": "2.5rem" } }
],
"lineHeight": true,
"letterSpacing": true,
"textDecoration": true,
"textTransform": true,
"fontWeight": true
}
}
}
The fluid typography feature, stabilized in WordPress 6.1 and refined in 6.6, automatically generates clamp() values for responsive font sizing. Instead of writing media queries, you define min and max sizes, and WordPress handles the responsive scaling between viewport breakpoints. According to the WordPress typography documentation, this is the recommended approach for responsive type in block themes.
The fontFace property registers local font files using the @font-face CSS rule automatically. Use the file:./ prefix to reference files relative to your theme directory. This replaces the older wp_enqueue_style() method for loading fonts and is significantly better for performance since WordPress can optimize font loading.
Spacing Settings
Spacing controls padding, margin, block gap, and defines a spacing scale that creates consistent rhythm across your theme.
{
"settings": {
"spacing": {
"padding": true,
"margin": true,
"blockGap": true,
"units": ["px", "em", "rem", "%", "vw"],
"spacingScale": {
"steps": 7,
"mediumStep": 1.5,
"unit": "rem",
"operator": "*",
"increment": 1.5
}
}
}
}
The spacingScale generates a geometric progression of spacing values. With the configuration above, WordPress generates 7 steps using a multiplier of 1.5, with the medium step at 1.5rem. This produces CSS custom properties like --wp--preset--spacing--20 through --wp--preset--spacing--80 that you can use throughout your theme. Alternatively, you can define explicit spacingSizes for full manual control.
Layout Settings
Layout settings control content width and wide alignment behavior across your entire theme.
{
"settings": {
"layout": {
"contentSize": "720px",
"wideSize": "1200px"
}
}
}
contentSize defines the default maximum width for block content. wideSize defines the maximum width when a block uses wide alignment. These values cascade through your entire theme. Every Group block, every template, every page respects these constraints unless overridden at the block level.
The appearanceTools Shorthand
Instead of enabling individual settings one by one, you can use the appearanceTools shorthand to enable a bundle of design controls at once:
{
"settings": {
"appearanceTools": true
}
}
This single property enables: border (color, radius, style, width), color.link, dimensions.minHeight, position.sticky, spacing (blockGap, margin, padding), and typography (lineHeight). It is a convenient starting point that you can then override selectively. As the official documentation notes, this is the recommended way to enable basic design controls for most themes.
The Styles Section: Applying Your Design System
While settings defines what is available, styles applies your actual design decisions. This is where you set default colors, typography, spacing, and element-level styling that WordPress compiles into CSS.
Global Styles
Global styles apply to the entire document and serve as your baseline design layer.
{
"styles": {
"color": {
"background": "var(--wp--preset--color--neutral-light)",
"text": "var(--wp--preset--color--neutral-dark)"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--body-font)",
"fontSize": "var(--wp--preset--font-size--medium)",
"lineHeight": "1.7"
},
"spacing": {
"padding": {
"top": "0",
"right": "var(--wp--preset--spacing--40)",
"bottom": "0",
"left": "var(--wp--preset--spacing--40)"
},
"blockGap": "var(--wp--preset--spacing--40)"
}
}
}
Notice how styles reference preset values using CSS custom property syntax: var(--wp--preset--color--primary). This ensures your styles stay connected to your settings. If you change the primary color in settings, every style that references it updates automatically.
Element Styles
Elements are HTML-level styling targets. You can style links, headings, buttons, captions, and cite elements globally.
{
"styles": {
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--primary)"
},
":hover": {
"color": {
"text": "var(--wp--preset--color--secondary)"
}
}
},
"heading": {
"typography": {
"fontWeight": "600",
"lineHeight": "1.3"
}
},
"h1": {
"typography": {
"fontSize": "var(--wp--preset--font-size--xx-large)"
}
},
"h2": {
"typography": {
"fontSize": "var(--wp--preset--font-size--x-large)"
}
},
"button": {
"border": {
"radius": "4px"
},
"color": {
"background": "var(--wp--preset--color--primary)",
"text": "#ffffff"
},
":hover": {
"color": {
"background": "var(--wp--preset--color--secondary)",
"text": "var(--wp--preset--color--neutral-dark)"
}
}
}
}
}
}
Element pseudo-states like :hover, :focus, and :active have been supported since WordPress 6.1. This eliminates the need for custom CSS for common interactive states.
Per-Block Styles
One of theme.json’s most powerful features is the ability to style individual block types. Every registered block can have its own default styles under styles.blocks.
{
"styles": {
"blocks": {
"core/code": {
"typography": {
"fontFamily": "var(--wp--preset--font-family--code-font)",
"fontSize": "var(--wp--preset--font-size--small)"
},
"color": {
"background": "#1a1a2e",
"text": "#e0e0e0"
},
"border": {
"radius": "6px"
},
"spacing": {
"padding": {
"top": "var(--wp--preset--spacing--30)",
"right": "var(--wp--preset--spacing--40)",
"bottom": "var(--wp--preset--spacing--30)",
"left": "var(--wp--preset--spacing--40)"
}
}
},
"core/quote": {
"border": {
"left": {
"color": "var(--wp--preset--color--primary)",
"width": "4px",
"style": "solid"
}
},
"spacing": {
"padding": {
"left": "var(--wp--preset--spacing--40)"
}
},
"typography": {
"fontStyle": "italic"
}
},
"core/navigation": {
"typography": {
"fontSize": "var(--wp--preset--font-size--small)",
"fontWeight": "500"
}
},
"core/post-title": {
"typography": {
"fontSize": "var(--wp--preset--font-size--xx-large)",
"fontWeight": "700",
"lineHeight": "1.2"
}
}
}
}
}
Per-block styles override global and element styles for that specific block type. This follows CSS specificity principles: block-level styles win over element-level styles, which win over global styles. WordPress generates scoped CSS selectors like .wp-block-code and .wp-block-quote to apply these without conflicts.
Block-Level Settings: Per-Block Feature Control
Just as you can apply styles per-block, you can control which settings are available on a per-block basis. This lets you restrict or expand design tools for specific blocks.
{
"settings": {
"blocks": {
"core/paragraph": {
"color": {
"custom": false
}
},
"core/heading": {
"typography": {
"fontSizes": [
{ "slug": "heading-sm", "size": "1.5rem", "name": "Heading Small" },
{ "slug": "heading-md", "size": "2rem", "name": "Heading Medium" },
{ "slug": "heading-lg", "size": "2.75rem", "name": "Heading Large" }
]
}
},
"core/button": {
"border": {
"radius": true
}
}
}
}
}
In this example, paragraphs cannot use custom colors (only palette colors), headings get a restricted font size scale, and buttons explicitly enable border radius controls. This granularity helps enforce design consistency while giving content creators appropriate flexibility.
Custom Templates and Template Parts
theme.json registers custom templates and template parts that become available in the Site Editor. This replaced the older PHP-based template registration system.
{
"customTemplates": [
{
"name": "page-no-title",
"title": "Page (No Title)",
"postTypes": ["page"]
},
{
"name": "page-full-width",
"title": "Full Width",
"postTypes": ["page", "post"]
},
{
"name": "page-landing",
"title": "Landing Page",
"postTypes": ["page"]
}
],
"templateParts": [
{
"name": "header",
"title": "Header",
"area": "header"
},
{
"name": "header-minimal",
"title": "Header (Minimal)",
"area": "header"
},
{
"name": "footer",
"title": "Footer",
"area": "footer"
},
{
"name": "sidebar",
"title": "Sidebar",
"area": "uncategorized"
}
]
}
Custom templates correspond to HTML files in your templates/ directory (e.g., templates/page-no-title.html). Template parts correspond to files in parts/ (e.g., parts/header.html). The area property for template parts tells WordPress where the part belongs, enabling proper handling in the Site Editor’s template part picker.
Custom Properties with the Custom Section
The settings.custom section lets you define arbitrary CSS custom properties that do not map to any specific WordPress feature but are available throughout your theme.
{
"settings": {
"custom": {
"contentWidth": "720px",
"sidebarWidth": "300px",
"headerHeight": "80px",
"transition": {
"duration": "200ms",
"timing": "ease-in-out"
},
"shadows": {
"small": "0 1px 3px rgba(0,0,0,0.12)",
"medium": "0 4px 12px rgba(0,0,0,0.15)",
"large": "0 8px 24px rgba(0,0,0,0.2)"
}
}
}
}
WordPress converts these into CSS custom properties using a predictable naming convention: --wp--custom--content-width, --wp--custom--transition--duration, --wp--custom--shadows--small. Nested objects produce hyphen-separated property names. This is invaluable for defining design tokens that CSS, block patterns, and template files can all reference.
Patterns: Registering Block Patterns in theme.json
Since WordPress 6.0, you can bundle block patterns with your theme by placing pattern PHP files in a patterns/ directory. theme.json complements this by letting you reference patterns from the WordPress.org pattern directory.
{
"patterns": [
"developer-starter/hero-section",
"developer-starter/featured-posts-grid"
]
}
This array references pattern slugs from the WordPress.org Pattern Directory. WordPress downloads and registers these patterns for your theme automatically. Combined with local patterns in the patterns/ directory, this gives theme developers a flexible system for providing starter content and layout options.
Complete Working theme.json Example
Below is a production-ready theme.json that implements everything covered in this guide. You can use this as a starting point for your own block themes and customize it to match your project requirements.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"appearanceTools": true,
"color": {
"custom": true,
"customGradient": true,
"defaultPalette": false,
"defaultGradients": false,
"palette": [
{ "slug": "primary", "color": "#1e3a5f", "name": "Primary" },
{ "slug": "secondary", "color": "#f0c040", "name": "Secondary" },
{ "slug": "accent", "color": "#2ecc71", "name": "Accent" },
{ "slug": "neutral-light", "color": "#f8f9fa", "name": "Light" },
{ "slug": "neutral-dark", "color": "#1a1a1a", "name": "Dark" },
{ "slug": "white", "color": "#ffffff", "name": "White" }
],
"gradients": [
{
"slug": "primary-gradient",
"gradient": "linear-gradient(135deg, #1e3a5f 0%, #2ecc71 100%)",
"name": "Primary Gradient"
}
]
},
"typography": {
"fluid": true,
"fontFamilies": [
{
"fontFamily": "'Inter', sans-serif",
"slug": "body",
"name": "Inter",
"fontFace": [
{
"fontFamily": "Inter",
"fontWeight": "400 700",
"fontStyle": "normal",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/inter-variable.woff2"]
}
]
},
{
"fontFamily": "'JetBrains Mono', monospace",
"slug": "mono",
"name": "JetBrains Mono",
"fontFace": [
{
"fontFamily": "JetBrains Mono",
"fontWeight": "400",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/jetbrains-mono-regular.woff2"]
}
]
}
],
"fontSizes": [
{ "slug": "small", "size": "0.875rem", "name": "Small", "fluid": { "min": "0.813rem", "max": "0.875rem" } },
{ "slug": "medium", "size": "1rem", "name": "Medium", "fluid": { "min": "0.938rem", "max": "1rem" } },
{ "slug": "large", "size": "1.25rem", "name": "Large", "fluid": { "min": "1.125rem", "max": "1.25rem" } },
{ "slug": "x-large", "size": "1.75rem", "name": "X-Large", "fluid": { "min": "1.5rem", "max": "1.75rem" } },
{ "slug": "xx-large", "size": "2.5rem", "name": "Huge", "fluid": { "min": "2rem", "max": "2.5rem" } }
],
"lineHeight": true,
"letterSpacing": true,
"textTransform": true,
"fontWeight": true
},
"spacing": {
"padding": true,
"margin": true,
"blockGap": true,
"units": ["px", "em", "rem", "%", "vw"],
"spacingSizes": [
{ "slug": "10", "size": "0.25rem", "name": "1" },
{ "slug": "20", "size": "0.5rem", "name": "2" },
{ "slug": "30", "size": "1rem", "name": "3" },
{ "slug": "40", "size": "1.5rem", "name": "4" },
{ "slug": "50", "size": "2rem", "name": "5" },
{ "slug": "60", "size": "3rem", "name": "6" },
{ "slug": "70", "size": "4.5rem", "name": "7" },
{ "slug": "80", "size": "6rem", "name": "8" }
]
},
"layout": {
"contentSize": "720px",
"wideSize": "1200px"
},
"custom": {
"transition": {
"duration": "200ms",
"timing": "ease-in-out"
},
"shadows": {
"small": "0 1px 3px rgba(0,0,0,0.12)",
"medium": "0 4px 12px rgba(0,0,0,0.15)"
}
}
},
"styles": {
"color": {
"background": "var(--wp--preset--color--neutral-light)",
"text": "var(--wp--preset--color--neutral-dark)"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--body)",
"fontSize": "var(--wp--preset--font-size--medium)",
"lineHeight": "1.7"
},
"spacing": {
"blockGap": "var(--wp--preset--spacing--40)",
"padding": {
"right": "var(--wp--preset--spacing--40)",
"left": "var(--wp--preset--spacing--40)"
}
},
"elements": {
"link": {
"color": { "text": "var(--wp--preset--color--primary)" },
":hover": { "color": { "text": "var(--wp--preset--color--secondary)" } }
},
"heading": {
"typography": { "fontWeight": "600", "lineHeight": "1.3" }
},
"h1": { "typography": { "fontSize": "var(--wp--preset--font-size--xx-large)" } },
"h2": { "typography": { "fontSize": "var(--wp--preset--font-size--x-large)" } },
"h3": { "typography": { "fontSize": "var(--wp--preset--font-size--large)" } },
"button": {
"border": { "radius": "4px" },
"color": { "background": "var(--wp--preset--color--primary)", "text": "#ffffff" },
":hover": { "color": { "background": "var(--wp--preset--color--secondary)", "text": "var(--wp--preset--color--neutral-dark)" } }
}
},
"blocks": {
"core/code": {
"typography": { "fontFamily": "var(--wp--preset--font-family--mono)", "fontSize": "var(--wp--preset--font-size--small)" },
"color": { "background": "#1a1a2e", "text": "#e0e0e0" },
"border": { "radius": "6px" },
"spacing": { "padding": { "top": "var(--wp--preset--spacing--30)", "right": "var(--wp--preset--spacing--40)", "bottom": "var(--wp--preset--spacing--30)", "left": "var(--wp--preset--spacing--40)" } }
},
"core/quote": {
"border": { "left": { "color": "var(--wp--preset--color--primary)", "width": "4px", "style": "solid" } },
"spacing": { "padding": { "left": "var(--wp--preset--spacing--40)" } }
},
"core/post-title": {
"typography": { "fontSize": "var(--wp--preset--font-size--xx-large)", "fontWeight": "700" }
},
"core/navigation": {
"typography": { "fontSize": "var(--wp--preset--font-size--small)", "fontWeight": "500" }
}
}
},
"customTemplates": [
{ "name": "page-no-title", "title": "Page (No Title)", "postTypes": ["page"] },
{ "name": "page-full-width", "title": "Full Width", "postTypes": ["page", "post"] }
],
"templateParts": [
{ "name": "header", "title": "Header", "area": "header" },
{ "name": "footer", "title": "Footer", "area": "footer" },
{ "name": "sidebar", "title": "Sidebar", "area": "uncategorized" }
]
}
Style Variations: Offering Multiple Design Options
Block themes can ship with multiple style variations, giving users the ability to switch entire color schemes and typography stacks without touching code. Style variations are JSON files placed in a styles/ directory in your theme root.
// styles/dark-mode.json
{
"version": 3,
"title": "Dark Mode",
"settings": {
"color": {
"palette": [
{ "slug": "primary", "color": "#64b5f6", "name": "Primary" },
{ "slug": "neutral-light", "color": "#1a1a1a", "name": "Light" },
{ "slug": "neutral-dark", "color": "#f0f0f0", "name": "Dark" }
]
}
},
"styles": {
"color": {
"background": "#121212",
"text": "#e0e0e0"
}
}
}
Users can switch between style variations in the Site Editor under Appearance > Editor > Styles > Browse Styles. Each variation can override any setting or style from the main theme.json. This is how themes like Twenty Twenty-Four offer multiple distinct looks within a single theme.
Best Practices and Common Patterns
After building and reviewing dozens of block themes, several patterns consistently produce better results.
1. Always Set defaultPalette and defaultGradients to False
WordPress ships with default color palettes and gradients. Unless you want those mixed with your brand colors, disable them. This keeps the editor clean and prevents users from accidentally choosing off-brand colors.
2. Use Fluid Typography for Every Font Size
Define fluid min/max values for every font size preset. This eliminates the need for media query-based font scaling and produces smoother responsive behavior across all viewport sizes.
3. Define a Consistent Spacing Scale
Whether you use spacingScale or manual spacingSizes, establish a clear progression. A geometric scale (each step is 1.5x the previous) produces natural visual rhythm. Use these spacing tokens everywhere instead of arbitrary pixel values.
4. Style Elements Before Blocks
Set sensible defaults for links, headings, and buttons at the element level first. Then override only where specific blocks need different treatment. This keeps your theme.json maintainable and follows the DRY principle.
5. Ship at Least One Style Variation
Even a simple dark/light mode variation demonstrates the power of theme.json to users and gives them immediate customization value without needing the Global Styles editor.
6. Use the $schema Property
Always include the $schema URL. VS Code, PHPStorm, and other editors with JSON Schema support will provide autocompletion, validation, and inline documentation as you edit theme.json. This catches typos and structural errors before you test in a browser.
Debugging and Validation
When theme.json does not produce the expected results, these debugging approaches help identify the issue quickly.
- Check the generated CSS — View page source and search for
wp--presetto see the CSS custom properties WordPress generated from your settings. Missing properties indicate a configuration error. - Validate against the schema — Run your theme.json through a JSON Schema validator using the WordPress schema URL. This catches structural issues like misplaced properties or wrong nesting.
- Use WP_DEBUG — With
WP_DEBUGenabled, WordPress logs theme.json parsing errors to the debug log. Checkwp-content/debug.logfor warnings about invalid values. - Check the REST API — The
/wp/v2/global-stylesendpoint shows the merged theme.json output including user customizations. Compare this against your source file to spot overrides. - Inspect block markup — Each block gets CSS classes that correspond to theme.json settings. Inspect elements in browser dev tools to trace which CSS custom property controls a specific style.
Performance Considerations
theme.json directly impacts front-end performance in several ways that developers should understand.
WordPress generates an inline <style> tag from theme.json on every page load. A theme.json with 200 custom properties generates more CSS than one with 50. Keep your settings focused on what you actually use. Remove unused font families, trim spacing scales to what the design requires, and avoid defining features you do not need.
Local font loading via fontFace is significantly more performant than Google Fonts. The fonts are served from the same domain (no DNS lookup), WordPress can add font-display: swap automatically, and preloading is handled natively. This aligns with Core Web Vitals best practices and the recommended typography approach in the WordPress developer handbook.
The WordPress performance team has noted that themes using theme.json consistently produce smaller CSS output compared to themes using traditional stylesheet approaches, because WordPress only generates CSS for the features you actually configure.
What Comes Next in the Block Theme Fundamentals Series
This is Article 1 of 6 in our Block Theme Fundamentals series. Now that you understand theme.json as the backbone of block theme configuration, upcoming articles will build on this foundation:
- How to Master theme.json (this article)
- Building Block Patterns That Scale — Creating reusable, maintainable patterns
- Template Parts and Template Hierarchy in Block Themes — Structuring your theme’s template system
- Advanced Block Theme Typography — Variable fonts, fluid type, type scales
- Custom Block Styles and Variations — Extending core blocks with custom styles
- Migrating Classic Themes to Block Themes — Step-by-step conversion guide
Each article expands on concepts introduced here, always referencing theme.json as the central configuration layer.
Start Building
theme.json is the foundation of every WordPress block theme. It replaces scattered PHP functions, multiple CSS files, and Customizer options with a single, declarative JSON configuration. Whether you are setting up color palettes, defining typography scales, configuring spacing systems, styling individual blocks, or registering templates, theme.json is where it all begins.
Take the complete example from this guide, drop it into a new block theme directory alongside your templates/ and parts/ folders, and start experimenting. The WordPress Site Editor will reflect your theme.json changes immediately, making it the fastest way to iterate on block theme design.
Need help building custom block themes for your WordPress projects? At brndle.com, we specialize in block theme development, FSE customization, and WordPress design systems. Get in touch to discuss your next project.
