Note: Everything I’m talking about here, including the code, is in beta mode. It will be subject to change. I’ll update this post after release to fix any code changes that may occur between now and then. I’m releasing this post now so that theme authors can start looking at their themes and thinking about how they might want to change the way they do options pages.

So, WordPress 3.4 has this nifty new feature you can find on the main Theme selection page. It’s a link next to each theme labeled “Customize”. This is the new Theme Customizer, and it’s way cool.

In fact, you can’t see what it does with a simple picture, so here’s a video. It’s available in HD if you want to go full screen. :)

So, now you know what it does, and if you’re a theme author, you’ve probably just gotten some great ideas. Here’s how you can implement those ideas in your theme.

First, note that if you already support the built in Custom Header and Custom Background functionality the WordPress core provides, then those will magically show up and work in the theme customizer. No extra code needed on your part.

Existing Options

Now, the first thing you’ll probably want to do is to take note of how your existing settings in the theme work. You have three main options for theme settings, realistically. I’ll go over them briefly.

1. “Theme mod”. This uses the set_theme_mod and get_theme_mod functions. It’s rare that themes actually use these since I wrote about the Settings API, but it is there and if you use these normally then it is supported by the Theme Customizer (in fact it’s the default).

2. Individual Settings. If you store your theme’s settings in the options table as individual rows, one per setting, then that works fine with the customizer. This is not the preferred way of doing things in themes, however, and not the most common. Still, some themes do this, so if you’re one of them, it’s supported as well.

3. Serialized Settings. This is the way I explained in my Settings API Tutorial and the method recommended by the Theme Review guidelines, as well as the way Chip described in his own tutorial for theme settings. Essentially, you store your settings in an array, then store that array using set_option or get_option, as one row in the database. This method is supported and it’s the way I’ll primarily cover in this article. I’ll briefly mention the other two methods when appropriate.

Once you know how your settings are stored, then you’ll know what to fill in at certain spots in the code. More on this when we get to it.

Object Orientation

Now, the Theme Customizer is very object oriented, and while you don’t necessarily need to understand this to implement the basics of it, you might need to understand it if you’re going to make something completely custom. Just a warning.

First, we’ll look at the left hand side of the customizer screen. Notice that the left hand side is divided into sections. Actually, that’s their name: WP_Customize_Section. In each of these sections is one or more controls; or rather, WP_Customize_Control. Finally, each of these controls one of more settings on the page: aka WP_Customize_Setting.

The Sections organize the controls. The Controls get input and pass it to the settings. The Settings interface with your existing options in the theme.

To make new stuff here for your own custom options, you need to know where to add it. That place is the customize_register action hook.

add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
	// ... do stuff ...

The function gets a parameter of the main $wp_customize object. This is the interface point where you will do everything like adding sections and controls and such.

Sections

So, first thing to do is to add a section. Here’s one way to do it:

	$wp_customize->add_section( 'themename_color_scheme', array(
		'title'          => __( 'Color Scheme', 'themename' ),
		'priority'       => 35,
	) );

The first parameter is a unique ID for the section that you’ll need later (when you’re putting controls into it). The second parameter is an array of options for the section. Sections don’t have a lot of options, really. You can give them a title, you can give them a “description” if you need some explanatory text in them. The priority setting determines their order in the list.

You can also give sections a “capability” if you have a special case. Generally speaking, most sites require the “edit_theme_options” capability to have users edit this sort of thing, and this is the default capability that the sections use. However, if you have options that anybody can edit, or which should only be managed by administrators, changing this capability will prevent the section from appearing to users who can’t change those settings anyway.

One final thing you can add to a section is a “theme_supports” option. This will make the menu not appear unless the theme supports something. If you’re putting this code in a theme itself, then you already know what the theme supports, so it doesn’t make much sense. The core uses this to not show the header and background options if the theme doesn’t support them.

Settings

Next, let’s configure some settings. Yes, the settings, not the controls. See, the controls need to know what settings they’re changing, so we have to attach the settings up first.

To declare a setting, you do it like this:

	$wp_customize->add_setting( 'themename_theme_options[color_scheme]', array(
		'default'        => 'some-default-value',
		'type'           => 'option',
		'capability'     => 'edit_theme_options',
	) );

In this case, I’ve declared that the setting I’m interested in is in an option, the option is named “themename_theme_options” in the database, and it’s serialized, and the actual array key in there is “color_scheme”. Remember that talk we had before about the Settings API and how you store your settings? This was method 3.

Here’s method 2 (one option per database entry):

	$wp_customize->add_setting( 'themename_color_scheme', array(
		'default'        => 'some-default-value',
		'type'           => 'option',
		'capability'     => 'edit_theme_options',
	) );

And here’s method 1 (using theme_mod):

	$wp_customize->add_setting( 'color_scheme', array(
		'default'        => 'some-default-value',
		'type'           => 'theme_mod',
		'capability'     => 'edit_theme_options',
	) );

This setting basically tells the theme customizer where the option is stored, and how to change it’s value so that your theme displays with the changed option.

Here’s the good bit about this: You’re telling the theme customizer where the option is. You don’t have to change the way the existing option works at all.

You already have a theme options page, right? So somehow, you’re saving those options. And in the theme, it’s reading those options using get_theme_mod or get_option, right? The way the theme customizer works is that it intercepts that call using a filter, changes the option for the previewer case only, and then passes the new option along to the theme. So the theme has no idea that the value it’s getting isn’t in the database, but one the user just selected. That’s the magic trick and why themes don’t have to dramatically change to support this sort of thing. All they have to do to make custom sections is to tell the theme customizer code what options they’re using and how, and it changes those options directly for the previewer.

(Note of clarification here: The “default” setting above should be a default value, not the current value. The difference is a subtle one, but the point is that you don’t actually need to get the current value of the option from the DB and put it in here. The WP_Customize_Setting takes care of all that jazz for you. The “default” is what should be used if the value doesn’t exist in the DB at all.)

There’s one more bit to the add_setting call that we’ll come back to later when I get around to explaining postMessage.

Controls

Finally, we come to the controls. Controls can look one of a lot of ways, obviously. The simplest controls are just checkboxes, or text fields. However, colors are something that change a lot, so there’s color wheel controls too. In fact, WordPress defines a number of possible controls. Let’s go over a few:

A radio selection:

	$wp_customize->add_control( 'themename_color_scheme', array(
		'label'      => __( 'Color Scheme', 'themename' ),
		'section'    => 'themename_color_scheme',
		'settings'   => 'themename_theme_options[color_scheme]',
		'type'       => 'radio',
		'choices'    => array(
			'value1' => 'Choice 1',
			'value2' => 'Choice 2',
			'value3' => 'Choice 3',
			),
	) );

Pretty simple. It’s referencing the section it’s in, the setting that it’s going to change, and then it has the radio type and the list of choices along with their associated values.

How about a checkbox instead? This one comes straight from core:

	$wp_customize->add_control( 'display_header_text', array(
		'settings' => 'header_textcolor',
		'label'    => __( 'Display Header Text' ),
		'section'  => 'header',
		'type'     => 'checkbox',
	) );

A checkbox is on or off, true or false. It needs no real values.

How about a selection dropdown box? Here’s an example:

	$wp_customize->add_control( 'example_select_box', array(
		'label'   => 'Select Something:',
		'section' => 'nav',
		'type'    => 'select',
		'choices'    => array(
			'value1' => 'Choice 1',
			'value2' => 'Choice 2',
			'value3' => 'Choice 3',
			),
	) );

The default type of control is actually type = ‘text’, and it creates a text box control. One more type of control is the “dropdown-pages” type, which creates a dropdown list of the WordPress Pages.

But that’s not all. There’s actually several more, but because they’re so custom, they’re declared differently. Here’s where we get all object oriented on ya…

	$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'link_color', array(
		'label'   => __( 'Link Color', 'themename' ),
		'section' => 'themename_color_scheme',
		'settings'   => 'themename_theme_options[link_color]',
	) ) );

Whoa, what’s with the new class? The WP_Customize_Color_Control is a class that is extending the built in WP_Customize_Control class. It adds the color wheel jazz to places where color selection is needed. Note that the class is being created here with new, and so it has to get the $wp_customize passed to it directly, so it knows where to hook in. (Note: This may change before final 3.4 release.)

Other controls of note:

  • WP_Customize_Upload_Control – This gives you an upload box, for allowing file uploads. However, you probably won’t use this directly, you’ll extend it for other things… like:
  • WP_Customize_Image_Control – This gives the image picker and the uploader box. It extends the upload controller. You can see it in action on the custom background piece, where a user can upload a new file to be the background image.
  • WP_Customize_Header_Image_Control – Because of the resizing action of the header piece, it needs a bit of special handling and display, so the WP_Customize_Header_Image_Control extends the WP_Customize_Image_Control to add that functionality. You can see it in action on the custom header piece, where a user can upload a new file to be the header image.

So, the way to create a custom controller to do whatever you want is to make a new class of your own which extends WP_Customize_Control and adds the bits you want. How to do that is a bit complex, so I’ll save that for another tutorial. For now, you’ve got image handling, color wheels, text boxes, radios, dropdowns, and checkboxes. I think that should be enough to get started with.

End of tutorial?

Not quite. Everything I went over above is enough to add new sections to the customizer, put controls in them, and then to have the preview show your changes after a slight delay when the page refreshes. All you have to do is to call those functions with the proper parameters, in the proper place, and it’ll work.

However, note that I said “when the page refreshes”… C’mon… this is the year 2012. We don’t have flying cars, and we still have to wait a whole second or two?

Nope.

Enter postMessage

Back when I mentioned the $wp_customize->add_setting function call, I mentioned “one more bit”. That one more bit is the option called “transport”.

Transport defines how your setting change gets from the place where you changed it into the preview pane. The default setting for this is “refresh”. An alternative setting is named “postMessage”.

The postMessage transport makes it such that the setting is instantly sent into the other frame, where javascript can adjust the page on-the-fly using this new information.

An example:

Let’s say we have a setting to change the colors of the titles. All the titles on the page are in some tag that has a class of posttitle, perhaps. The option normally just saves the HTML color chosen, then outputs some inline CSS in the header.php to basically do this:

.posttitle {
	color: #abcdef;
}

Or whatever the option actually is for that color.

We have hooked our setting to that option, and hooked our WP_Customize_Color_Control up to it, and now when we change it, it works and we can see the color change. Note that this is easiest to do with already working customizer options, so the best way to do it is to get it working normally first, then add on this next bit.

Now, we have the working option in the customizer, so to take away that refresh delay, we’ll add this new option to the add_setting call:

	'transport'         => 'postMessage',

This tells the customizer that the setting will be sent directly to the frame via javascript. However, for that setting to work, we need javascript in the frame itself to receive it.

So, back in our main function… remember that? It started like this:

add_action( 'customize_register', 'themename_customize_register' );
function themename_customize_register($wp_customize) {
	// ... do stuff ...

Right at the end of that function, we’re going to add this code:

	if ( $wp_customize->is_preview() && ! is_admin() )
		add_action( 'wp_footer', 'themename_customize_preview', 21);

This is going to add a new function call to our preview frame’s footer. It only gets added with the preview frame, so the live site and others won’t see it, because they don’t need to see it. This is where we’re going to output our javascript to make things happen in real-time.

Here’s our function:

function themename_customize_preview() {
	?>
	<script type="text/javascript">
	( function( $ ){
	wp.customize('setting_name',function( value ) {
		value.bind(function(to) {
			$('.posttitle').css('color', to ? to : '' );
		});
	});
	} )( jQuery )
	</script>
	<?php 
} 

As you can see, it just outputs a bit of javascript. This code won’t change much, ever, so let’s go over just two pieces of importance:

  • ‘setting_name’ is the name of the setting, as added by the $wp_customize->add_setting call.
  • The entire line starting with jQuery(‘.posttitle’) is our custom bit of code. It gets the “to” variable, which will be the color chosen by the user, and it sets the posttitles on the page to have that color, using the css modifying functionality of jquery.

Those are the only two bits you need to change, really. The rest is pretty copy-pasta. For each real-time setting, you can dupe this bit of code in the script.

Here’s another thing: You can change pre-existing refresh settings to be postMessage ones. Take the Site Title and Tagline elements in the Header section, for example. These are refresh settings, and the reason they are is because each theme implements them differently. There’s no way for the core to know the javascript code needed for any particular theme.

But if you’re a theme author, then you’re not writing for a generic theme. You’re writing for your particular theme. You know how the site title and tagline are displayed. There’s no reason you can’t make those update in real time. And while you’re at it, the header_textcolor setting can be real time too, since you know the theme code.

In your main function again, add these three lines of code:

	$wp_customize->get_setting('blogname')->transport='postMessage';
	$wp_customize->get_setting('blogdescription')->transport='postMessage';
	$wp_customize->get_setting('header_textcolor')->transport='postMessage';

That changes the transport on those core settings to be postMessage. Now you need to add the javascript code to actually do the refreshing in your theme. Here’s an example of TwentyEleven doing this (with the patch I wrote for it):

function twentyeleven_customize_preview() {
	?>
	<script type="text/javascript">
	( function( $ ){
	wp.customize('blogname',function( value ) {
		value.bind(function(to) {
			$('#site-title a').html(to);
		});
	});
	wp.customize('blogdescription',function( value ) {
		value.bind(function(to) {
			$('#site-description').html(to);
		});
	});
	wp.customize( 'header_textcolor', function( value ) {
		value.bind( function( to ) {
			$('#site-title a, #site-description').css('color', to ? to : '' );
		});
	});
	} )( jQuery )
	</script>
	<?php
}

For the blogname, it changes the HTML inside the “#site-title a” link. For the description, it changes the tag with #sitedescription. For the color of those, it simply targets both of them and alters their CSS.

Core has to try to be generic across all themes. But themes have more knowledge of how they work and can change things to target themselves in better ways. A theme adding controls knows what those controls change, so if it’s something simple like CSS or even something more complex like HTML, if you can write javascript code to make that modification in real time, then you can use postMessage and eliminate that refresh delay.

Hopefully this explains some of the theme customizer. Was it as clear as mud? Take a look at my patch to Twenty Eleven to add some of the theme options from its existing options screen into the customizer. You can find it on this ticket: http://core.trac.wordpress.org/ticket/20448.

Shortlink:

241 Comments

  1. [...] to add the settings is not the focus of this post so you should check out posts like “How to leverage the Theme Customizer in your own themes” instead for great explaining on how to use the [...]

  2. [...] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on the Theme Customization API. Additional tutorials on the Theme Customization API are available at the Ottopress.com website. [...]

  3. Hi,
    I have gone through every explanation I can find online and followed this to the letter but cannot get the values to change using the java-script, I can en-queue the script and can see the values changing within the site when I save but cannot get the wp.customize() java-script call to do anything even just alert.
    Is there any reason why this wouldn’t work? wp.customize(‘heading_colour’,function( value ){alert(‘Hello World’)});
    Any assistance would be great as I know it must be something silly.

  4. [...] thanks to Otto and his Theme Customizer tutorial, which I referred to more than a few times when getting IceChimp’s Customizer to work [...]

  5. Hi Otto,
    In the line $('.posttitle').css('color', to ? '#' + to : '' );, you add a # to the color value. I couldn’t make the code work, and realised it is because WP already returns the hex value prefixed with a #. The line works if I change it to $('.posttitle').css('color', to ? to : '' );. Hope that helps people!

  6. [...] For more information, take a look at Otto on WordPress’ video tutorial or guide to integrating the theme customizer into your own themes. [...]

  7. [...] (Hey WP core developers, customise is spelled with a damn s!) it yet. All I could find was this description of the beta version. Also there doesn’t seem to be an API yet, it must be coming in a [...]

  8. [...] For more information, take a look at Otto on WordPress’ video tutorial or guide to integrating the theme customizer into your own themes. [...]

  9. [...] For more information, take a look at Otto on WordPress’ video tutorial or guide to integrating the theme customizer into your own themes. [...]

  10. Otto I’m wondering does the WP_Customize_Image_Control stores other information about the image as well? Width and height maybe?

  11. [...] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on the Theme Customization API. Additional tutorials on the Theme Customization API are available at theOttopress.com website. [...]

  12. Has anyone ever figured out a simple way to create a setting to add classes to a container when a check box control is checked? I’m trying to come up with a way to add push and pull classes to my main content area and sidebar to swap the sidebar from left to right. The best I’ve come up with so far is to add a script that uses jQuery append() to add them the push pull classes where needed and wrap the enqueue for that script in a conditional statement that checks if a that checkbox is checked. That seems like an awfully complicated method though…

  13. […] For more information, take a look at Otto on WordPress’ video tutorial or guide to integrating the theme customizer into your own themes. […]

  14. […] so you can try it out using that theme. There’s a great video on the Ottopress blog showing you how the Customizer works with Twenty Eleven. Using it is […]

  15. Any option that will allow us to embed youtube videos?

  16. How to write array setting name (like themename_theme_options[color_scheme] ) in javascript code and “transport” ? Thanks

  17. Unless I’m missing the point (completely possible), the “theme supports” option goes well with parent theme design. For example, if I have a timeline script that has to be enabled via add_theme_support() in the child functions, then I probably also have a bunch of options that I need to display in the customizer as well. Those options will be super out of place if the child theme designer doesn’t enable the feature that they support.

    So I think that’s the reason for “theme supports” – though I’m going to have to read up on its usage to be sure. If you’re developing a one-off theme, no, it doesn’t make any sense. If you’re developing a parent framework in a modular way, it’s going to be a godsend.

  18. As always, thanks for these awesome, life-saving, theme customizer tutorials. Quick question:

    When using serialized options and I use get_setting do I use the theme slug and setting name or just option name?

    IE:
    For a setting called slug[some_setting] do I use:

    $wp_customize->get_setting(‘some_setting’)->transport=’postMessage’;
    or:
    $wp_customize->get_setting(‘slug[some_setting]‘)->transport=’postMessage’;

  19. Otto,

    What would cause the defaults theme options written within the customize_register action hook to not appear when you first activate the theme on the themes page that has these theme customizer options written? I can successfully see the theme options defaults render on the ‘Customize’ page but on the client side those settings don’t appear. For example I have a color picker that sets the background color of a footer and the output from the client side shows the css except for the setting default of the color like so:


    .site-footer {
    background: ;
    }

    The color doesn’t output? But on the ‘Customize’ page it will show the background color.

    Another thing is that if I do change a default setting and then hit ‘Save and Publish’ it will then show all the default options that have been written within the custom_register action hook. It just won’t output those defaults when you first apply the theme.

  20. I’m getting this error:
    Fatal error: Call to a member function check_capabilities() on a non-object in /path/to/website/public/wp-includes/class-wp-customize-control.php on line 160

    Anyone knows what it could be??

  21. hi, is there a way to enable uploading custom header images in customizer?

  22. […] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on theTheme Customization API. Additional tutorials on the Theme Customization API are available at the Ottopress.com website. […]

  23. […] in the first tutorial, I talked about the various controls available in the customizer. Specifically I mentioned image […]

  24. […] in the first tutorial, I talked about the various controls available in the customizer. Specifically I mentioned image […]

  25. […] week I have had my nose buried learning all about the WordPress Theme Customizer, I have come to the conclusion that for most themes nowadays we can use that instead of a theme […]

  26. […] week I have had my nose buried learning all about the WordPress Theme Customizer, I have come to the conclusion that for most themes nowadays we can use that instead of a theme […]

  27. […] For more information, take a look at Otto on WordPress’ video tutorial or guide to integrating the theme customizer into your own themes. […]

  28. […] How to leverage the Theme Customizer in your own themes […]

  29. Otto,

    Thanks for the incredible writeup. It has helped me out tremendously in getting more adept with the wp customzier. I’ve created a ton of stuff for the WP Customzier and all is well, except one thing that I am stuck on. I’ve created a stylsheet switcher in the WP Customizer that gives a user the ability to select a pre-coded stylesheet with a dropdown. All works well on the php side and when you select a stylesheet from the dropdown, it does show the changes after you ‘save’ and refresh. But I can’t seem to get the live preview to work for this. My jQuery seems to work great for all of the other live previews, but for whatever reason, I can’t seem to create a functional live preview for the theme switcher.

    I’ve added my php and jQuery to pastebin here. Wondering if you could maybe take a look and see where I’m falling on my face. If you can, I’d appreciate it greatly.

    php => http://pastebin.com/K8jkeXXH

    jQuery => http://pastebin.com/ubyAMj1r

    Again, if you could take a peek, I’d greatly appreciate it. Thanks in advance.

    • I assume that “beast-style-switcher-css” is the ID of your link element?

      If that’s the case, then “$switcher.href” is incorrect, I believe. You would need to do “$switcher.attr(‘href’,newStyle)” instead.

  30. […] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on the Theme Customization API. Additional tutorials on the Theme Customization API are available at theOttopress.com website. […]

  31. Cracking back into extending the WP Theme Customizer…. I created a custom file uploader for .ico files to populate favicon links. But I’m also curious in uploading & extracting .zip files into specific folders such as “/fonts/” if it exist, and if not create it in theme directory and extract files into them. Currently they are just going into the uploads root folder, which is ok for now, but would help to create a subdirectory there or in the themes root directory.

    Are there any references anywhere that you know of to help with extracting content from a zip file by using

    WP_Customize_Upload_Control

    Overall, this is to achieve uploads for .zip font-glyphs from icomoon.io

  32. […] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on the Theme Customization API. Additional tutorials on the Theme Customization API are available at the Ottopress.com website. […]

  33. […] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on the Theme Customization API. Additional tutorials on the Theme Customization API are available at the Ottopress.com website. […]

  34. […] Theme and plugin developers interested in adding new options to a theme’s Theme Customization page should see the documentation on the Theme Customization API. Additional tutorials on the Theme Customization API are available at theOttopress.com website. […]

  35. […] Say you have built a really amazing WordPress theme, and have enabled its users to tailor it to suit their needs with a really amazing custom section in the Theme Customizer (that you put together after following one or more of these Theme Customizer tutorials): […]

  36. […] How to leverage the Theme Customizer in your own themes […]

  37. […] “Otto” Wood on the customizer: Parts One (basic utilization), Two (dumping options pages), and Three (custom […]

  38. […] Any control willing to populate the Theme Customizer must extend the WP_Customize_Control class. That class extension must be made at customize_register hook time. For major and well more detailed info see Otto on WordPress article. […]

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Need to post PHP code? Wrap it in [php] and [/php] tags.