Skip to content

Instantly share code, notes, and snippets.

@ericandrewlewis
Last active October 9, 2024 00:31
Show Gist options
  • Save ericandrewlewis/2310fd6d7dabf0696965 to your computer and use it in GitHub Desktop.
Save ericandrewlewis/2310fd6d7dabf0696965 to your computer and use it in GitHub Desktop.
The WordPress Customizer

The WordPress Customizer

The WordPress Customizer is an interface for drafting changes to content while previewing the changes before they are saved. This is an alternative to the "save and suprise" model of changing settings without knowing what exactly will happen.

The customizer can be accessed in the admin interface under Appearance > Customize.

A screenshot of the customizer

#19909 is the trac ticket that introduced the Customizer during the 3.4 release cycle.

Daryl Koopersmith spoke about his experience building the Customizer at jQuery Conference SF 2012.

API Overview

The Customizer loads UI to draft content — e.g. site title, widgets, menus, etc.

This UI is created with the Customizer API, which can be used to create more UI. e.g. if you want to have editable, custom CSS, you can create UI to draft it in the customizer. Because it is visual in nature, custom CSS is a great use-case for editing with a live preview.

The Customizer API consists of four object types: settings, controls, sections, and panels.

A setting is an encapsulated piece of data. e.g. a site option, a theme modification, a navigation menu item, an instance of a widget. It's responsibility is to manage the state of the data (getting its value, setting its value, etc.).

A control is a piece of UI in the Customize frame for drafting changes to the content. e.g. the textbox to edit the Site Title or the more complicated widget area editing interface. A control is bound to a setting; editing the value in the UI control will change the drafted value of the setting.

Sections and panels are grouping containers for controls. A control lives inside a section lives inside a panel.

See a basic example that adds Custom CSS to the Customizer.

Internals Overview

The customizer frame includes the UI to make draft changes to content which appears on the left, and an embedded preview frame on the right.

Components of the customizer

The customizer frame can be thought of as a single page JavaScript application which sends AJAX requests to get preview content and to save data. Customizer objects are registered server-side to populate a JavaScript settings object which is dropped on the page. JavaScript object instances are created from this settings object.

The preview frame's content is "stuffed" via JavaScript. Content is retrieved via an AJAX POST request. Data for the drafted changes is passed in as a POST variables with the request, so the drafted changes can be considered while building a preview response server-side. The response body is then stuffed into the preview iframe. Some content changes can be made without hitting the server, e.g. changing the background color does not require any server side changes. This depends on the settings "transport."

Customizer objects are also registered server-side in preview requests. This is required so the setting can configure the filtering required to modify the data inside the preview.

Load the customizer anywhere

The customizer can be configured to load anywhere in a WordPress site.

A screenshot of the customizer

This depends on the customize-loader script. When any element with the class load-customize is clicked, the customizer loads in a modal on top of the page. e.g.

<?php
/*
 * Enqueue the `customizer-loader` script on the Post Edit screen.
 */
add_action( 'admin_enqueue_scripts', function($hook_suffix) {
	if ( in_array( $hook_suffix, array( 'post.php', 'post-new.php' ) ) ) {
		wp_enqueue_script( 'customize-loader' );
	}
} );

/*
 * Add a button in the Submit meta box that, on click, opens the customizer.
 */
add_action( 'post_submitbox_misc_actions', function() {
	?>
	<button class="load-customize" href="<?php echo esc_url( wp_customize_url() ) ?>" type="button">Custom button to open customizer</button>
	<?php
} );

Change the URL to be previewed

By default, the homepage will be previewed. Any arbitrary URL can be previewed by setting the url query string parameter in the element's href attribute. e.g.

$customize_url = add_query_arg(
	array( 'url' => urlencode( home_url() . '/page-to-preview/' ) ),
	wp_customize_url()
);
?><button class="load-customize" href="<?php echo esc_url( $customize_url ) ?>" type="button">Custom button to open customizer</button>

Deeplink to a panel or section

A panel or a section can be deeplinked to. e.g. to initialize into the widget panel context,

$customize_url = add_query_arg(
	array( 'autofocus' => array( 'panel' => 'widgets' ) ),
	wp_customize_url()
);
?>
<button class="load-customize" href="<?php echo esc_url( $customize_url ) ?>" type="button">Custom button to open customizer</button>

More detail on the Customizer API

Settings

A setting takes the form of a PHP object and a JavaScript object, for different purposes.

A setting is registered server-side in the Customizer Frame request. Registered settings are output for the JavaScript customize frame bootstrap which creates JavaScript settings objects.

Settings are registered server-side in a preview request. A setting that should always show in the Customizer can be registered always (e.g. in the manner Site Title gets registered). Dynamic settings should be registered based on relevant state passed into the preview request (e.g. the URL or $_POST['customized'] data). Only the controls and sections "active" in a preview request are displayed; inactive ones will trigger the respective UI to hide in the controls pane.

When a preview request is created server-side, registered settings will filter the object's data they relate to with the drafted changes.

Settings are also registered server-side in a save request.

Controls

A control should be registered server-side in the Customizer frame request. Registered are output for the JavaScript customize frame bootstrap, which will create JavaScript control objects which populate the controls pane.

A control should be registered server-side in a preview request. Only controls that are registered in a preview request will be displayed in the Customize frame's controls pane; inactive ones are hidden. This hides controls based on the context of the page being previewed. e.g. controls to edit a widget area that only shows on the homepage is visible when the previewed page is the homepage, but hidden when previewing a single post.

Sections & Panels

A control must be registered with a section.

A section may be registered with a panel. If no panel is specified a panel will be made for the section.

Examples

Custom CSS editable in the Customizer

Custom CSS per post, editable with the Customizer from the Edit Post screen

See the Customizer API documentation for further detail.

@bueltge
Copy link

bueltge commented Nov 9, 2015

I provide a example to use the Customizer for more as theme functions, like customizing of the login screen - https://github.com/bueltge/customizer-sandbox All information, source inside this repo. Maybe helpful as additional resources for this Gist.

@ahmadawais
Copy link

Thanks, Eric! Great info!

@mohdsayed
Copy link

Very helpful, thanks

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