Skip to content

Template Style Variations (Exploration/POC)#75330

Open
costasovo wants to merge 6 commits into
WordPress:trunkfrom
costasovo:template-styles-exploration
Open

Template Style Variations (Exploration/POC)#75330
costasovo wants to merge 6 commits into
WordPress:trunkfrom
costasovo:template-styles-exploration

Conversation

@costasovo

@costasovo costasovo commented Feb 8, 2026

Copy link
Copy Markdown
Contributor

What?

Exploratory prototype for template-specific style variations — allowing individual templates to use distinct global style configurations instead of inheriting a single site-wide set of styles.

This is a proof of concept and is not intended to be merged as-is. It is meant to validate the architecture and inform a proposal (see #75331).

Note: The style variation picker in the template sidebar is a placeholder UI for demonstration purposes. A more natural home for this would likely be the existing style browser in the Styles panel, where a user could choose whether to apply a style variation site-wide or scope it to the current template.

Why?

The current global styles system operates site-wide: every template inherits the same theme.json settings and user customizations. This proposal makes it easier to support real-world scenarios like:

  • Seasonal or campaign pages that need unique color schemes and typography without affecting the rest of the site.
  • Multi-brand sites where different sections require distinct design systems.
  • Plugin-provided templates (e-commerce, email, forums) that need tailored styles complementing — but not overriding — the site theme.

How?

The feature is gated behind the gutenberg-template-style-variations experiment flag (Gutenberg > Experiments). Nothing is loaded or registered unless the experiment is enabled.

Architecture

Data model — three entities and their relationships:

  1. Style Variations — registered sets of theme.json-compatible styles/settings (similar to theme style variations, but scoped to templates). Stored in a WP_Style_Variations_Registry singleton; plugins and themes register them via gutenberg_register_style_variation().

  2. Base Themes — optional alternative theme.json configurations that replace the active theme's base layer. Registered via gutenberg_register_base_theme(). A style variation can reference a base theme to start from a completely different design foundation.

  3. Templates — link to a style variation by ID via post meta (_wp_style_variation_id on wp_template). Multiple templates can share the same variation.

How variations become editable:

When a user edits a variation's styles in the Styles UI, a wp_global_styles post is created for that variation (linked via _wp_source_variation_id meta). This post stores user customizations scoped to the variation, parallel to how the default wp_global_styles post stores site-wide customizations. The relationship is one-to-one: one post per variation, shared by all templates using it.

Style merge order (matching the existing global styles cascade):

Core defaults → Block styles → Theme (or Base Theme) → Variation user customizations

REST API for third-party integration:

Endpoint Purpose
GET /wp/v2/style-variations List registered variations
GET /wp/v2/base-themes List registered base themes
PATCH /wp/v2/templates/{id} Set/unset style_variation on a template
POST /wp/v2/templates-variation-post/{id} Get or create the editable wp_global_styles post for a variation

PHP registration API for plugins/themes:

// Register a style variation
gutenberg_register_style_variation( 'my-plugin//dark-mode', array(
    'title'      => 'Dark Mode',
    'base_theme' => 'my-plugin//dark-base', // optional
    'data'       => array( /* theme.json-compatible styles/settings */ ),
) );

// Register a base theme
gutenberg_register_base_theme( 'my-plugin//dark-base', array(
    'title' => 'Dark Base',
    'data'  => array( /* full theme.json structure */ ),
) );

Demo

The PR includes demo code (lib/experimental/demo-template-style-variations.php) that exercises the registration API — it registers two base themes and five style variations, and creates a "Campaign Landing Page" template with an assigned variation. This serves as a practical reference for how plugins and themes would use gutenberg_register_style_variation() and gutenberg_register_base_theme().

Testing Instructions

  1. Enable the experiment: Gutenberg > Experiments > Template Style Variations.
  2. Go to Appearance > Editor > Templates. You should see a "Campaign Landing Page" template with warm-toned styling in its preview.
  3. Open any template for editing. In the sidebar, a "Style Variation" panel shows a picker with the registered variations.
  4. Select a variation (e.g., "Dark Mode") and save. The editor canvas should update to use that variation's styles.
  5. Visit the template on the frontend — the variation styles should be applied there as well.
  6. Open the Styles sidebar while a variation is active — edits are scoped to the variation, not the global styles.

Screenshots or screencast

template_styles.mp4

@github-actions

github-actions Bot commented Feb 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: .

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

github-actions Bot commented Feb 8, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: costasovo <costasovo@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: mtias <matveb@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions Bot added [Package] Core data /packages/core-data [Package] Editor /packages/editor [Package] Edit Site /packages/edit-site labels Feb 8, 2026
…for template style variations

Introduces the foundational backend infrastructure for template style
variations — an experimental feature that allows assigning distinct
global-style configurations to individual templates.

New registries:
- WP_Style_Variations_Registry_Gutenberg (singleton) for style variations
- WP_Base_Themes_Registry_Gutenberg (singleton) for base themes

Public PHP API (lib/template-style-variations.php):
- Register/unregister style variations and base themes
- Get/set variation assignments for templates
- Manage variation-specific wp_global_styles posts

REST endpoints:
- GET /wp/v2/style-variations — list registered variations
- GET /wp/v2/base-themes — list registered base themes
- POST /wp/v2/templates-variation-post/{id} — create/get variation posts

Gated behind the gutenberg-template-style-variations experiment flag.
Connects the JavaScript editor to the PHP REST API and makes the
global styles system template-variation-aware.

core-data changes:
- New actions, reducers, resolvers for fetching registered style
  variations and base themes from REST API
- New selectors: __experimentalGetRegisteredStyleVariations,
  __experimentalGetBaseThemes

editor changes:
- TemplateStyleVariationContext + Provider — React context that
  tracks the current template's variation ID, post ID, and base theme
- useGlobalStyles() now reads the variation context to serve
  variation-specific styles and edits instead of global ones
- GlobalStylesProvider wraps children in TemplateStyleVariationProvider
- GlobalStylesRenderer integrates with template-aware styles
- Exports useGlobalStyles as private API
@costasovo costasovo force-pushed the template-styles-exploration branch from 9dd3143 to 38246ac Compare February 8, 2026 15:17

@tyxla tyxla left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @costasovo, this looks useful and quite a frequently requested feature (see more details here).

As it's very late in the 7.0 cycle, this has a minimal chance to land on time, so it will likely need to be slated for as early as 7.1.

Still, I think it's worth broader feedback: cc @WordPress/gutenberg-core

Comment thread pnpm-lock.yaml Outdated
User-facing UI for selecting and previewing template style variations.

New components:
- TemplateStyleVariationPicker — grid of visual previews for each
  registered variation, fetches post data for user edits, allows
  selecting a variation for the current template
- TemplateStyleVariationPanel — sidebar panel shown when editing
  templates in the site editor

Modified:
- Template list fields now use usePatternSettingsWithVariation() to
  render variation-aware previews in the template listing
- global-styles-ui exports TemplateStyleVariationPicker
Makes the editor canvas render using the template's assigned variation
styles. This is needed because useSpecificEditorSettings() runs outside
the TemplateStyleVariationProvider context.

New:
- TemplateStyleVariationProvider wrapper for the site editor

Modified:
- use-site-editor-settings.js — useTemplateStyleVariationLookup()
  reads post data when available, falls back to registered data;
  mergeGlobalStyles() overlays variation styles onto editor settings
- editor/index.js — integrates TemplateStyleVariationProvider and
  passes resolvedTemplateId
PHP that generates the correct stylesheet on the actual site (not the
editor) for templates that have an assigned style variation.

Modified:
- WP_Theme_JSON_Resolver_Gutenberg — new methods:
  get_merged_data_for_template() (core merge method),
  get_theme_data_with_base(), get_user_data_from_post(),
  get_user_data_from_registered_variation()
- global-styles-and-settings.php —
  gutenberg_get_global_stylesheet_for_template()
- script-loader.php — gutenberg_enqueue_global_styles() now uses
  template-specific stylesheet when a variation is assigned
Example data for testing the template style variations feature.
Only loaded when the gutenberg-template-style-variations experiment
flag is enabled.

Registers 2 base themes (minimal, dark-base) and 5 style variations
(dark-mode, warm-tones, cool-tones, high-contrast, pastel-colors).
@costasovo costasovo force-pushed the template-styles-exploration branch from 38246ac to e919100 Compare February 9, 2026 11:46
@youknowriad

Copy link
Copy Markdown
Contributor

I think @mtias has explored something similar in a previous PR. Might be good to check approaches and ideas :)

@tyxla

tyxla commented Feb 9, 2026

Copy link
Copy Markdown
Member

Yep, that's the PR in question: #73978

@mtias

mtias commented Feb 16, 2026

Copy link
Copy Markdown
Member

Yes, it's very similar, but the architectures differ a bit. It'd be good to start breaking it down into components.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Core data /packages/core-data [Package] Edit Site /packages/edit-site [Package] Editor /packages/editor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants