Style Variations and Section Styles

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This sub-section’s WordPress bibliography lists the reference material consulted while preparing these pages.

A block theme can offer more than one look without more than one theme. Theme style variations are alternative theme.json files that restyle the whole site; colour and typography presets are smaller variations that change only the palette or only the fonts; block style variations add named styles (the "Styles" buttons in the block sidebar) to particular blocks; and section styles are block style variations for container blocks such as Group and Columns that restyle everything inside them, including links, headings and nested blocks. This page builds all four for the Lumen Press theme lumen: two full variations, "Paper" and "Midnight", one colour preset, one typography preset, a dark section style defined in JSON and a highlight section style and a pull-quote style defined in PHP.

This page was written against WordPress 7.1.3 (released 2026-10-06; 7.1.4, a security release of 2026-10-28, is the version to run in production), PHP 7.4 minimum and 8.3+ recommended, theme.json version 3 and WP-CLI 2.12.0, and checked on 2026-10-28. WordPress 7.2 is in beta and due in December 2026; nothing on this page depends on it. Every listing and every generated CSS rule shown below comes from a 7.1.3 site running the lumen files of this page.

The settings and styles that variations contain are the ordinary theme.json ones, described in theme.json Settings and theme.json Styles. How a site owner picks a variation in the Site Editor, and what is stored when they do, is described in Site Editor and Global Styles.

Four mechanisms at a glance

Mechanism Where it lives Where users choose it Since

Theme style variation

styles/<name>.json without blockTypes

Styles > Browse styles

6.0

Colour preset (palette)

a styles/ file containing only colour data, conventionally styles/colors/<name>.json

Styles > Colors > Palette

6.6

Typography preset (typeset)

a styles/ file containing only typography (and spacing) data, conventionally styles/typography/<name>.json

Styles > Typography

6.6

Block style variation

register_block_style() in PHP, wp.blocks.registerBlockStyle() in JavaScript, or a block’s block.json styles

Block sidebar > Styles

5.0 (JavaScript), 5.3 (PHP)

Section style (block style variation with nested styles)

styles/<name>.json with blockTypes, or register_block_style() with style_data

Block sidebar > Styles on Group, Columns and other listed blocks

6.6

Theme style variations

What a variation file is

Every .json file in the theme’s styles/ folder, including subfolders, is read as a theme.json partial. The file carries version, an optional title (the file name is used without one), and the settings and styles to apply on top of the theme’s own theme.json. A variation does not need to repeat anything it does not change; it is merged over the theme’s data in the same way the theme’s data is merged over the core defaults. The theme’s theme.json itself is the "Default" entry of the list.

The decision of what kind of variation a file is follows two rules, both visible in the WordPress source:

  • a file with a top-level blockTypes array is a block style variation (a section style); every other file is a theme variation (WP_Theme_JSON_Resolver::style_variation_has_scope());

  • among theme variations, the Site Editor shows a file as a colour preset if all its settings and styles sit under keys named color, as a typography preset if they all sit under keys named typography or spacing, and as a full variation (Browse styles) otherwise. The folder name is only a convention; the content decides.

The Lumen files used on this page:

lumen/
├── style.css, theme.json
├── functions.php
├── templates/index.html
└── styles/
    ├── paper.json             Full variation "Paper"
    ├── midnight.json          Full variation "Midnight"
    ├── section-dark.json      Section style (has "blockTypes")
    ├── colors/
    │   └── archive.json       Colour preset "Archive"
    └── typography/
        └── sans-headings.json Typography preset "Sans Headings"

The base theme.json

The variations below only make sense against the base palette, so here is the part of lumen/theme.json they rely on (the complete file, with layout, spacing and fluid type, is built in theme.json Settings). The styles.blocks entry at the end customizes the section style for one block type and is explained in Overriding a section style per block type.

{
	"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
	"version": 3,
	"settings": {
		"appearanceTools": true,
		"layout": { "contentSize": "680px", "wideSize": "1140px" },
		"color": {
			"defaultPalette": false,
			"palette": [
				{ "slug": "paper", "name": "Paper", "color": "#fbf8f1" },
				{ "slug": "ink", "name": "Ink", "color": "#1f1d1a" },
				{ "slug": "lumen-red", "name": "Lumen red", "color": "#a3271f" },
				{ "slug": "mist", "name": "Mist", "color": "#e9e4d8" },
				{ "slug": "slate", "name": "Slate", "color": "#4a4740" }
			]
		},
		"typography": {
			"fontFamilies": [
				{ "slug": "source-serif", "name": "Source Serif", "fontFamily": "\"Source Serif 4\", Georgia, serif" },
				{ "slug": "system-sans", "name": "System sans", "fontFamily": "system-ui, -apple-system, \"Segoe UI\", sans-serif" }
			]
		}
	},
	"styles": {
		"color": { "background": "var:preset|color|paper", "text": "var:preset|color|ink" },
		"typography": { "fontFamily": "var:preset|font-family|source-serif" },
		"elements": { "link": { "color": { "text": "var:preset|color|lumen-red" } } },
		"blocks": {
			"core/columns": {
				"variations": { "section-dark": { "spacing": { "padding": { "top": "3rem", "bottom": "3rem" } } } }
			}
		}
	}
}

The most useful habit for variations is visible here: styles refer to palette slugs, never to hex values. A variation then only has to redefine the colours behind the slugs, and every style, block and pattern that uses paper or ink follows. A variation that introduces new slugs instead leaves blocks that saved the old slugs with no colour at all.

"Paper" and "Midnight"

"Paper" is the print look: pure white, black text, underlined links that lose the underline on hover, and lighter headings. It keeps every slug and only changes the values.

{
	"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
	"version": 3,
	"title": "Paper",
	"settings": {
		"color": {
			"palette": [
				{ "slug": "paper", "name": "Paper", "color": "#ffffff" },
				{ "slug": "ink", "name": "Ink", "color": "#111111" },
				{ "slug": "lumen-red", "name": "Lumen red", "color": "#8f1f18" },
				{ "slug": "mist", "name": "Mist", "color": "#f2f0eb" },
				{ "slug": "slate", "name": "Slate", "color": "#55524b" }
			]
		}
	},
	"styles": {
		"typography": { "lineHeight": "1.7" },
		"elements": {
			"heading": { "typography": { "fontWeight": "400" } },
			"link": {
				"typography": { "textDecoration": "underline" },
				":hover": { "typography": { "textDecoration": "none" } }
			}
		}
	}
}

"Midnight" is the dark look. Because the base styles say "background is paper, text is `ink`", swapping the two values is enough to invert the whole site; the file then adds what only the dark look needs: the sans-serif font, filled buttons and a coloured rule on quotes.

{
	"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
	"version": 3,
	"title": "Midnight",
	"settings": {
		"color": {
			"palette": [
				{ "slug": "paper", "name": "Paper", "color": "#14161c" },
				{ "slug": "ink", "name": "Ink", "color": "#ece8de" },
				{ "slug": "lumen-red", "name": "Lumen red", "color": "#ff8a7a" },
				{ "slug": "mist", "name": "Mist", "color": "#232733" },
				{ "slug": "slate", "name": "Slate", "color": "#b5b0a4" }
			]
		}
	},
	"styles": {
		"typography": { "fontFamily": "var:preset|font-family|system-sans" },
		"elements": {
			"button": { "color": { "background": "var:preset|color|lumen-red", "text": "var:preset|color|paper" } }
		},
		"blocks": { "core/quote": { "border": { "left": { "color": "var:preset|color|lumen-red", "width": "3px" } } } }
	}
}

The slugs keep their names in Midnight even though paper is now dark: variations may change preset values but must never rename slugs, or content that saved them loses its colours. Check the contrast of each variation’s text and link colours (4.5:1 for body text) as described in Accessibility; a palette that passes in the default look does not automatically pass in the dark one.

Colour and typography presets (6.6)

Since WordPress 6.6 a theme can ship partial variations that a site owner combines freely: the Colors panel lists palettes and the Typography panel lists typesets, so the owner can, for example, keep the default layout, take the "Archive" palette and the "Sans Headings" fonts. Neither appears in Browse styles. The Archive preset contains colour data only:

{
	"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
	"version": 3,
	"title": "Archive",
	"settings": {
		"color": {
			"palette": [
				{ "slug": "paper", "name": "Paper", "color": "#f4ecd8" },
				{ "slug": "ink", "name": "Ink", "color": "#2b2118" },
				{ "slug": "lumen-red", "name": "Lumen red", "color": "#7a3b12" },
				{ "slug": "mist", "name": "Mist", "color": "#e6dcc3" },
				{ "slug": "slate", "name": "Slate", "color": "#5c4f3d" }
			]
		}
	},
	"styles": {
		"color": { "background": "var:preset|color|paper", "text": "var:preset|color|ink" }
	}
}

The typography preset contains typography data only; it reuses the font families declared in theme.json (a preset may also declare its own settings.typography.fontFamilies, including fontFace entries, which is how a typeset can bring new self-hosted fonts, see Typography and Fonts):

{
	"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
	"version": 3,
	"title": "Sans Headings",
	"styles": {
		"typography": { "fontFamily": "var:preset|font-family|source-serif", "lineHeight": "1.6" },
		"elements": {
			"heading": {
				"typography": { "fontFamily": "var:preset|font-family|system-sans", "fontWeight": "600", "letterSpacing": "-0.01em" }
			}
		}
	}
}

A single extra property breaks the classification. Adding "styles": { "spacing": … } to Archive, or a color value to the typeset, turns either file into a full variation that appears in Browse styles instead. The Site Editor makes the decision in the browser (the isVariationWithProperties() check in the global styles code), so there is no server-side warning; the quickest check is to open the Colors and Typography panels after adding a file.

Listing the variations

WP_Theme_JSON_Resolver::get_style_variations() returns the parsed files of the active theme (and of its parent, see Child themes and variations). Its $scope argument, added in 6.6, selects theme variations (theme, the default) or block style variations (block). The REST route /wp/v2/global-styles/themes/<stylesheet>/variations, which the Site Editor calls, returns the theme scope. The script below lists both scopes, then reads the merged global styles, which is also the moment the JSON section styles are registered as block styles:

<?php
// wp eval-file list-variations.php
foreach ( array( 'theme', 'block' ) as $scope ) {
	foreach ( WP_Theme_JSON_Resolver::get_style_variations( $scope ) as $variation ) {
		$applies_to = isset( $variation['blockTypes'] ) ? implode( ', ', $variation['blockTypes'] ) : 'whole site';
		WP_CLI::log( sprintf( '%-5s  %-20s %s', $scope, $variation['title'], $applies_to ) );
	}
}

// Reading the merged data registers the partials as block styles.
$group = wp_get_global_styles( array( 'blocks', 'core/group', 'variations' ) );
WP_CLI::log( 'styles.blocks.core/group.variations: ' . implode( ', ', array_keys( $group ) ) );

$registry = WP_Block_Styles_Registry::get_instance();
foreach ( array( 'core/group', 'core/cover', 'core/quote' ) as $block ) {
	$names = array_keys( $registry->get_registered_styles_for_block( $block ) );
	WP_CLI::log( sprintf( 'registered for %-11s %s', $block . ':', implode( ', ', $names ) ) );
}

On the Lumen site, with the functions.php of the next section active:

theme  Archive              whole site
theme  Midnight             whole site
theme  Paper                whole site
theme  Sans Headings        whole site
block  Section dark         core/group, core/columns, core/cover
styles.blocks.core/group.variations: section-dark, section-highlight
registered for core/group: section-highlight, section-dark
registered for core/cover: section-dark
registered for core/quote: pull-quote

Applying a variation in the Site Editor copies its values into the user layer; no "active variation" is stored, so later edits to styles/midnight.json do not reach a site that applied Midnight until the owner applies it again (see Site Editor and Global Styles). Three more details: the files are sorted by path, so colors/archive.json comes before midnight.json; a theme that wants a particular order in Browse styles prefixes the file names (01-paper.json, 02-midnight.json), as Twenty Twenty-Five does. The resolver returns presets and full variations together; only the Site Editor separates them. And a variation file’s strings (title, palette name) are translated with the theme’s text domain, so they belong in the theme’s translation files like any other string.

Child themes and variations

Since 6.2 a child theme inherits its parent’s variations: the resolver reads the child’s styles/ folder, then the parent’s, and drops a parent file when the child has a file with the same base name. A lumen-child that ships styles/midnight.json therefore replaces the parent’s Midnight entirely (it does not merge with it), while Paper and the presets still come from lumen. Because only the base name is compared, lumen-child/styles/dark/midnight.json also hides lumen/styles/midnight.json. Child themes are covered in Child Themes.

Block style variations

A block style variation is a named style of one block type. Selecting it in the block sidebar adds the class is-style-<name> to the block; the block’s markup does not change otherwise. Core blocks declare their own in block.json (Button "Fill" and "Outline", Image "Rounded", Quote "Plain", Separator "Wide line" and "Dots", Table "Stripes", Social Icons "Logos only" and "Pill shape", and others), and themes and plugins add more.

Registering in PHP

register_block_style( $block_name, $style_properties ) (5.3) registers a style on the server, which makes it available in the editor and, if it carries CSS, prints that CSS on the front end only on pages that use the block. The properties are:

Property Meaning Since

name

Required. The slug in the class is-style-<name>

5.3

label

Required. The translatable button label

5.3

inline_style

CSS printed after the block’s own stylesheet

5.3

style_handle

Handle of a registered stylesheet to enqueue for the style

5.3

is_default

Marks the style as the block’s default

5.3

style_data

theme.json-shaped style data (colour, typography, spacing, border, elements, blocks); WordPress generates the CSS and exposes the style in Styles > Blocks

6.6

Since 6.6 the first argument may also be an array of block names, registering one style for several blocks. Lumen registers a classic CSS style for Quote and a section style in PHP for Group and Columns:

<?php
/**
 * Lumen theme functions: block style variations registered in PHP.
 *
 * @package lumen
 */

add_action( 'init', 'lumen_register_block_styles' );

/**
 * Registers the theme's PHP block styles.
 */
function lumen_register_block_styles() {
	// A classic block style: a class plus hand-written CSS.
	register_block_style(
		'core/quote',
		array(
			'name'         => 'pull-quote',
			'label'        => __( 'Pull quote', 'lumen' ),
			'inline_style' => '.wp-block-quote.is-style-pull-quote { border: 0; font-size: 1.5em; text-align: center; }',
		)
	);

	// A section style in PHP: theme.json-shaped data, several block types (6.6+).
	register_block_style(
		array( 'core/group', 'core/columns' ),
		array(
			'name'       => 'section-highlight',
			'label'      => __( 'Section highlight', 'lumen' ),
			'style_data' => array(
				'color'    => array(
					'background' => 'var:preset|color|mist',
					'text'       => 'var:preset|color|ink',
				),
				'border'   => array(
					'left' => array(
						'color' => 'var:preset|color|lumen-red',
						'width' => '4px',
						'style' => 'solid',
					),
				),
				'elements' => array(
					'link' => array(
						'color' => array( 'text' => 'var:preset|color|lumen-red' ),
					),
				),
			),
		)
	);
}

The inline_style route is what older tutorials teach, and it still has its place for effects that theme.json cannot express. Its drawback is that the CSS is invisible to Styles: the site owner cannot change the pull-quote’s size in the Site Editor, and its selector (0-2-0) beats the 0-1-0 global styles. style_data styles are generated from theme.json data, are listed under Styles > Blocks > Group > Style variations, and follow the active variation’s palette. A theme can also override them from theme.json (as shown for section-dark below), which the Theme Handbook page on block style variations still describes as unsupported; the 7.1.3 resolver merges styles.blocks.<block>.variations.<name> over registered style_data as it does for JSON partials.

Registering in JavaScript and unregistering

Styles can also be registered in the editor only, with wp.blocks.registerBlockStyle() in a script enqueued on enqueue_block_editor_assets; such styles need their CSS from a stylesheet loaded on both sides. Removing styles follows where they came from:

  • unregister_block_style( $block_name, $style_name ) removes only styles registered with register_block_style(). Run it on init with a later priority than the registration;

  • core styles declared in a block’s block.json (Quote "Plain", Button "Outline") are not in the registry, so the PHP function returns false for them; remove them in the editor with wp.blocks.unregisterBlockStyle() inside wp.domReady().

On the Lumen site unregister_block_style( 'core/quote', 'plain' ) returns false and unregister_block_style( 'core/quote', 'pull-quote' ) returns true. Removing a style only hides the button; content that already carries is-style-plain keeps the class, and whether it still looks styled depends on whether the CSS for that class is still loaded.

Section styles

What a section style is

Before 6.6 a block style variation could only style the block it was applied to. Since 6.6 the data of a variation may contain elements (links, headings, buttons inside the block) and blocks (styles for inner block types), so a single "Section dark" style on a Group can turn the whole section dark: background, text, link and heading colours, and the buttons and separators inside it. This is what the 6.6 release calls section styles. Nesting works because 6.6 also reduced global styles selectors to 0-1-0 specificity with :root :where(…), so the rules of an inner section override those of an outer one by source order, not by selector weight.

A section style as a JSON partial

The recommended way for a theme is a theme.json partial in styles/ with three extra top-level keys: blockTypes (the block types that offer the style), slug (the class name part) and title (the label). Lumen’s dark section for newsletter sign-ups and featured quotes, styles/section-dark.json:

{
	"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
	"version": 3,
	"title": "Section dark",
	"slug": "section-dark",
	"blockTypes": [ "core/group", "core/columns", "core/cover" ],
	"styles": {
		"color": { "background": "var:preset|color|ink", "text": "var:preset|color|paper" },
		"spacing": { "padding": { "top": "2rem", "right": "2rem", "bottom": "2rem", "left": "2rem" } },
		"elements": {
			"heading": { "color": { "text": "var:preset|color|paper" } },
			"link": {
				"color": { "text": "var:preset|color|mist" },
				":hover": { "color": { "text": "var:preset|color|paper" } }
			}
		},
		"blocks": {
			"core/separator": { "color": { "text": "var:preset|color|slate" } },
			"core/button": { "color": { "background": "var:preset|color|paper", "text": "var:preset|color|ink" } }
		}
	}
}

When WordPress reads the theme data it calls the private wp_register_block_style_variations_from_theme_json_partials() for every file with blockTypes, registering section-dark for each listed block unless a style of that name already exists, and copies the file’s styles into styles.blocks.<block>.variations.section-dark. A partial has no settings (only styles are used), and a file without blockTypes or without styles is skipped.

Because the colours are preset references, the section adapts to the theme variation: under Midnight, ink is the light colour, so "Section dark" becomes a light band on a dark page. If a section must stay dark in every variation, it should refer to slugs whose meaning does not flip, or the dark variation should override it (next section).

Overriding a section style per block type

The same style can be refined for one block type from theme.json (or from a theme variation) under styles.blocks.<block>.variations.<slug>; the values are merged over the partial’s. The base theme.json above gives the Columns version more vertical padding. The resolver applies, from highest to lowest priority: styles.blocks.<block>.variations in theme.json, the top-level styles.variations in theme.json, the JSON partials, and the registry’s style_data. The top-level styles.variations form was announced as "not recommended" in the 6.6 dev note and should be avoided in new themes.

A user can then change the root styles of each variation per block in Styles > Blocks > Group (or Columns); those values go to the user layer like any other global style.

The generated markup and CSS

Global styles do not contain a rule for .is-style-section-dark. Instead, when a block with a section style renders on the front end, the render_block_data filter wp_render_block_style_variation_support_styles() resolves the variation’s data and generates a stylesheet scoped to a per-instance class, and the render_block filter adds that class to the block’s wrapper. The CSS is added to the inline style handle block-style-variation-styles, so it is printed only on pages that use the style. A newsletter section saved by the editor:

<!-- wp:group {"className":"is-style-section-dark","layout":{"type":"constrained"}} -->
<div class="wp-block-group is-style-section-dark"><!-- wp:heading -->
<h2 class="wp-block-heading">The Lumen Press newsletter</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>New titles every month. <a href="https://lumenpress.test/books/">Browse the catalogue</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:buttons -->
<div class="wp-block-buttons"><!-- wp:button -->
<div class="wp-block-button"><a class="wp-block-button__link wp-element-button" href="https://lumenpress.test/newsletter/">Subscribe</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons --></div>
<!-- /wp:group -->

The script below renders that markup as the front end does and prints the inline CSS queued for it:

<?php
// wp eval-file render-section.php newsletter.html
$markup = file_get_contents( $args[0] );
echo do_blocks( $markup ), "\n\n";

// The per-instance CSS is queued on this handle while the block renders.
echo implode( "\n", wp_styles()->get_data( 'block-style-variation-styles', 'after' ) ), "\n";

The wrapper div of the Group comes back with the instance class appended, is-style-section-dark--1 (the inner blocks are unchanged), followed by the CSS (rules split one per line for reading):

:root :where(.is-style-section-dark--1 a:where(:not(.wp-element-button))){color: var(--wp--preset--color--mist);}
:root :where(.is-style-section-dark--1 a:where(:not(.wp-element-button)):hover){color: var(--wp--preset--color--paper);}
:root :where(.is-style-section-dark--1 h1, .is-style-section-dark--1 h2, .is-style-section-dark--1 h3, .is-style-section-dark--1 h4, .is-style-section-dark--1 h5, .is-style-section-dark--1 h6){color: var(--wp--preset--color--paper);}
:root :where(.is-style-section-dark--1 .wp-block-separator){color: var(--wp--preset--color--slate);}
:root :where(.is-style-section-dark--1 .wp-block-button .wp-block-button__link){background-color: var(--wp--preset--color--paper);color: var(--wp--preset--color--ink);}
:root :where(.wp-block-group.is-style-section-dark--1){background-color: var(--wp--preset--color--ink);color: var(--wp--preset--color--paper);padding-top: 2rem;padding-right: 2rem;padding-bottom: 2rem;padding-left: 2rem;}

On a real request the same CSS appears in <style id="block-style-variation-styles-inline-css"> in the page head. The same Columns block with the style gets padding-top: 3rem and padding-bottom: 3rem from the theme.json override and keeps the 2rem side padding from the partial, and the PHP-registered section-highlight produces the same shape of output from its style_data:

:root :where(.is-style-section-highlight--1 a:where(:not(.wp-element-button))){color: var(--wp--preset--color--lumen-red);}
:root :where(.wp-block-group.is-style-section-highlight--1){background-color: var(--wp--preset--color--mist);border-left-color: var(--wp--preset--color--lumen-red);border-left-width: 4px;border-left-style: solid;color: var(--wp--preset--color--ink);}

The inline_style of the pull quote is instead appended to the Quote block’s own wp-block-quote-inline-css style.

Several consequences follow from this design:

  • the --1, --2 suffixes come from wp_unique_id() and depend on the order of blocks in the request, so theme or plugin CSS must never target .is-style-section-dark--1; target .is-style-section-dark if extra CSS is needed;

  • each instance gets its own copy of the rules, so a page with twenty dark sections prints twenty small rule sets; this is rarely significant, but a pattern repeated in a Query Loop multiplies it;

  • only the first is-style-* class that has data is used; a block cannot combine two section styles;

  • styles set on the block instance itself (its colour or padding in the sidebar) win over the section style, which is the intended order;

  • since 7.1 the per-instance stylesheet is generated with the theme’s settings.viewport, so responsive and state values inside a variation follow the same breakpoints as the rest of the theme (responsive styles are described in theme.json Styles).

Nesting and limits

A dark section can sit inside a highlighted one and the inner rules win, but a variation cannot contain another variation, a section style cannot restyle the block style variations of its inner blocks, and section partials accept no settings (so a section cannot offer its own palette in the colour picker), as the 6.6 dev note states.

Versions

Version Change

5.3

register_block_style(), unregister_block_style() in PHP (registerBlockStyle() in JavaScript has existed since 5.0)

6.0

Theme style variations in styles/*.json, listed in Styles > Browse styles

6.2

Child themes inherit the parent’s variations; a child file with the same base name replaces the parent’s

6.6

theme.json version 3; colour and typography presets; get_style_variations( $scope ); blockTypes and slug in partials; style_data and arrays of block names in register_block_style(); elements and blocks inside variations (section styles); 0-1-0 global styles specificity

7.1

Variation stylesheets honour settings.viewport; responsive and state styles available inside variations

What older books get wrong or leave out

Older advice Current state (7.1)

A different colour scheme needs a child theme, a Customizer colour control or a premium theme’s options panel (UWH, PRO)

A block theme ships alternative looks as styles/*.json files; owners pick them in Styles > Browse styles, or combine a palette and a typeset since 6.6.

Block styles are "a CSS class plus a stylesheet"

Still possible with inline_style, but since 6.6 style_data and JSON partials generate the CSS from theme.json data, appear in Styles and follow the active palette.

Dark bands and highlighted boxes are built with custom CSS classes typed into "Additional CSS class(es)"

Section styles give the same result as a named style in the block sidebar, with nested links, headings and buttons styled from data.

Site Editor walkthroughs for 6.3 and 6.4 show one list of variations (AIO)

Since 6.6 colour and typography presets are listed separately in the Colors and Typography panels.

Theme design chapters stop at the Customizer and do not cover theme.json (PRO, UWH)

Every mechanism on this page is theme.json data; see theme.json Settings and theme.json Styles.

Common errors and pitfalls

Symptom Cause and fix

A colour preset shows up in Browse styles

The file contains something besides colour data (a spacing or typography value, an elements style without color). Keep presets to color keys only, or typography and spacing only.

A section style appears as a whole-site variation

blockTypes is missing or misspelt; without it the file is a theme variation.

The section style does not appear for a block

The block is not in blockTypes, the file has no styles, or the JSON does not parse (the file is then silently skipped). Validate with the $schema in an editor.

Content lost its section style after a theme update

The title changed and there is no slug, so the generated slug, and the class in saved content, changed. Always set slug and never change it.

Custom CSS for .is-style-section-dark--1 works on one page only

The instance number is per request. Target .is-style-section-dark.

A section style’s values are ignored on one block

That block has its own colour or spacing set in the sidebar, which wins. Clear the local value.

unregister_block_style() returns false

The style comes from block.json or JavaScript; remove it with wp.blocks.unregisterBlockStyle() in the editor.

Editing styles/midnight.json changes nothing on a site that uses Midnight

Applying a variation copied its values into the user layer. Apply it again or reset Styles.

A child theme’s variation is merged with the parent’s

It is not: a same-named child file replaces the parent file entirely. Copy the whole file into the child and change it there.

Security notes: variation files are data, not code, but style_data and inline_style are printed into the page as CSS, so they must never be built from user input, and they deserve the same review as any theme stylesheet.

Themes Overview, Theme Patterns (patterns that apply section-dark to their outer Group), Child Themes and Accessibility.