Universal Themes: Customization

Making Global Styles and the Customizer work together

In the last post we shared the idea of a “universal” theme. This post looks at how we can use classic WordPress tools (in this case the Customizer) to customize a block theme, while saving these changes in Global Styles – making a universal theme!

Global Styles Everywhere

Block themes use a theme.json file to define many aspects of the theme, e.g. color palettes and typography. Gutenberg provides a tool to edit these settings (called Global Styles). When a user changes these values in the Global Styles UI, the changes are not saved back into the theme.json file but instead are saved to a Custom Post Type (CPT) in WordPress. Because this CPT can be modified using WordPress APIs, this gives us the power to make changes to Global Styles without relying on the interface in Gutenberg.

This simple idea is the basis for the color and typography customization options we have added to our universal theme Blockbase. The rest is just implementation details…

Implementation details!

When the Customizer loads, we create two new sections:

  1. Colors
  2. Fonts
		'capability'  => 'edit_theme_options',
		'description' => sprintf( __( 'Color Customization for %1$s', 'blockbase' ), $theme->name ),
		'title'       => __( 'Colors', 'blockbase' ),
		'capability'  => 'edit_theme_options',
		'description' => sprintf( __( 'Font Customization for %1$s', 'blockbase' ), $theme->name ),
		'title'       => __( 'Fonts', 'blockbase' ),

In each of these sections we create new settings and controls – each setting and control relates to a color/font option in Global Styles. We read the content of the theme.json file and use this to populate the settings in the Customizer. There is a helpful function in Gutenberg which merges together the theme.json settings with any user settings:


We read in an array of color palettes from the theme.json file and display these inside the “Colors” section:


One of the powers of Global Styles is that it relies on CSS variables. This makes it very easy for us to update the Customizer preview when the controls are changed. Some simple javascript injects new values for these CSS variables into the page, meaning that the preview updates instantly.

First we bind a listener to the control:

// For each of the palette items add a listener
userColorPalette.forEach( ( paletteItem ) => {
	const settingName = userColorSectionKey + paletteItem.slug;
	wp.customize( settingName, ( value ) => {
		value.bind( ( newValue ) => {
			paletteItem.color = newValue;
			blockBaseUpdateColorsPreview( userColorPalette );
		} );
	} );
} );

This updates the global variable userColorPalette, which we then use to create our CSS variables:

function blockBaseUpdateColorsPreview( palette ) {
	// build the CSS variables to inject
	let innerHTML = ':root,body{';
	palette.forEach( ( paletteItem ) => {
		innerHTML += `--wp--preset--color--${ paletteItem.slug }:${ paletteItem.color };`;
	} );
	innerHTML += ';}';

	// inject them into the body
	const styleElement = document.getElementById(
	styleElement.innerHTML = innerHTML;


Customizer settings are usually saved in a site option or a theme mod. Since we are building a universal theme, we need to save these changes into Global Styles so that they are reflected in the Site Editor. The easiest way we found to achieve this was to hook into the customize_save_after action, read the settings from the controls, and then update the Global Styles CPT with the new settings. This code is used to get and read the CPT:

get_post( $user_custom_post_type_id );
json_decode( $user_theme_json_post->post_content );

Once you have the CPT in JSON form it’s simply a case of adding the new settings to it, and saving them back into the CPT:

$user_theme_json_post_content->settings->color->palette = $this->user_color_palette;

wp_update_post( json_encode( $user_theme_json_post_content ) );

Color Palettes

Color palettes are simply combination of color settings. When a user selects a palette we simply change all of the associated colors at once. This can be done with the Javascript API:

wp.customize.control( userColorSectionKey ).setting.set( color );

How can I use this?

The code above is just pseudo code, to explain the concepts. For a fully working example see Blockbase freely available in our free themes repository. This code has a GPL license and can therefore be copied and distributed freely.

However, if you are interested in building a universal theme I would encourage you to use Blockbase as a parent theme. This will mean you get all future improvements to your theme for free!


The Customizer gets a bad rap, and it’s true that it is clunky when compared to the direct manipulation that is possible with Gutenberg. Nevertheless, building these kinds of tools to update Global Styles without the framework of the Customizer would have been much more involved. There is some satisfaction in being able to take advantage of all the hard work that has gone into the Customizer in its final years!

Author: Ben Dwyer

I make things. I particularly like to make music. Music is meant to be fun, that's why it's 'played'.