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:

260 Comments

  1. Otto, excellent article, are you planning to write the advanced one soon “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. ”

    I was trying to build a customised version of radio buttons that use images as pickers rather than the button/text. I started by trying to build my own ‘extends WP_Customize_control’ by taking WP_Customize_Image_Control as an example, but I got a bit lost. I’m sure with the insight of an advance tutorial I might be able to get that sorted. For the time being I guess a bit of image html in the ‘radio’ choices will be an approximation.

    Keep up te good work.

    • @ Alan Fuller Did you ever have any luck with the images and radio buttons?
      Any html that I enter into the string for my radio button just comes out as plain text. Is there a way around this?

  2. Oh dear, my plan of adding html to the image choices fails, as it seems it gets displayed as pure text. Another cunning plan would be to use css, but unfortunately each of the radio buttons don’t have a unique class or id. So it looks like I’m stuck with raw text until I can get to grips with extending the classes.

  3. I’m rather confused as to how to get this to work….

    I’ve created a theme-options.php an am including it in my functions.php like so

    require_once ( ‘library/theme-options.php’ );

    Then in the theme-options.php i have the following:

    add_section( ‘themename_color_scheme’, array(
    ‘title’ => __( ‘Color Scheme’, ‘themename’ ),
    ‘priority’ => 35,
    ) );

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

    }

    ?>

    but nothing shows up when i customize the them in the customizer. Sorry for the noobishness, i’m no php programmer.

    -jeremy

    • Nevermind i was being a Renob. I wasn’t calling my add_control and my variables were messed up. I got it setup.

    • After some modifications, it works beautifully 🙂

      add_action( 'customize_register', 'forthgear_customize_register' );
      
      function forthgear_customize_register($wp_customize) {
      	
      	$wp_customize-&gt;add_section( 'color_scheme', array(
          'title'          =&gt; __( 'Color Scheme', 'themename' ),
          'priority'       =&gt; 35,
      ) );
      
      	$wp_customize-&gt;add_setting( 'primary_color', array(
      	'default'        =&gt; '#000000',
      	'type'           =&gt; 'option',
      	'capability'     =&gt; 'edit_theme_options',
      ) );
      	$wp_customize-&gt;add_setting( 'secondary_color', array(
      	'default'        =&gt; '#ff0000',
      	'type'           =&gt; 'option',
      	'capability'     =&gt; 'edit_theme_options',
      ) );
      
      $wp_customize-&gt;add_control( new WP_Customize_Color_Control( $wp_customize, 'primary_color', array(
      	'label'   =&gt; __( 'Primary Color', 'themename' ),
      	'section' =&gt; 'color_scheme',
      	'settings'   =&gt; 'primary_color',
      ) ) );
      
      $wp_customize-&gt;add_control( new WP_Customize_Color_Control( $wp_customize, 'secondary_color', array(
      	'label'   =&gt; __( 'Secondary Color', 'themename' ),
      	'section' =&gt; 'color_scheme',
      	'settings'   =&gt; 'secondary_color',
      ) ) );
      
      	
      }
      

      in my theme-options.php

  4. I must be missing a step i have to do before i do all of this, correct me if i’m wrong, this is for getting your “options” to show up in the customizer, But don’t i have to do some steps before this about declaring the colors etc using add_theme_support() or something like that?

  5. Hi Otto. This all looks great, but I think I’ve reached a potential bug, and i hope you can enlighten me if that’s not the case.

    I use one database option to store all my options (the serialized method), but that doesn’t seem to play 100% nice with the js postMessage thing.

    This code:

    wp.customize( 'my_options[option_name]', function( value ) {
    console.log(value());
    value.bind( function( to ) {
    $( 'body' ).html( to );
    } );
    } );

    always outputs value() in the console, but somehow if the option is a serial one the javascript that should update thins without refreshing does not work.

    The same identical scenario as above works if I have a single option:


    wp.customize( 'blogname', function( value ) {
    console.log(value());
    value.bind( function( to ) {
    $( 'body' ).html( to );
    } );
    } );

    Is this a known issue?

  6. Wow, that was fast! Thanks.

    Yes, I tried it, what I implied (sorry for the ambiguity) was that the inner bind function doesn’t run at all.

    i.e. this


    wp.customize( 'my_options[option_name]', function( value ) {
    console.log(value());
    value.bind( function( to ) {
    console.log('do I run? if yes what is the value of "to"? easy, it is > ' + to);
    $( 'body' ).html( to );
    } );
    } );

    only outputs the first log, the second does not run, it isn’t just that ‘to’ doesn’t have the value I would expect, I don’t even know what it is.

    and, not sure if this is relevant, the data-customize-setting-link attribute on the field is “my_options[option_name]” too

    • Maybe the filter that hijacks the updated form field is not being able to emulate the writing of a serialized option?

      i.e. (I have no idea of how it works) if the filter has to emulate a single option update it can, but if it has to parse that option and update one of the inner options it can’t?

    • What is “value()” supposed to be? Just remove that line entirely.

      • Sure.. I can remove it, I was just trying to see whether there was any way to have javascript output what i was typing in the form field, since the body on the right was not being updated with the new value. As I said I am just a bit lost on the “why the same identical code works with a single option but it doesn’t with a serialised option 🙂

        • No, I mean, “value” isn’t a function. “value()” makes no sense, and may stop JS execution.

          • When I log console.log(value) there console gives me this back.

            But anyway, I removed it and tried, same issue. To be 100% sure I just tried this test code in this exact same environment:


            $wp_customize->add_setting( 'single_test', array(
            'default' => '',
            'type' => 'option',
            'capability' => 'edit_theme_options'
            ) );
            $wp_customize->add_control( 'single_test', array(
            'label' => 'Single Test',
            'section' => 'test_section',
            'settings' => 'single_test',
            'type' => 'text',
            'priority' => 999
            ) );
            $wp_customize->get_setting('single_test')->transport='postMessage';

            then added this as javascript:


            wp.customize( 'single_test', function( value ) {
            value.bind( function( to ) {
            $( 'body' ).html( to );
            } );
            } );

            and it works perfectly

            • Did you ever find a solution? I am trying to use the customizer with theme options as well, IE: themeoptionsname[link_color] and the live preview doesn’t work.

              • Unfortunately I didn’t, and I am considering switching to single wp_options db entries because of it.

                I am creating a github repository that showcases the problem so I can send the link to Otto and the rest of the dev team. If there is in fact a “bug” or an issue with the customizer of some sort, they will definitely have an easier time catching it with a live example/case study 🙂

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

  8. Hey Otto –
    Awesome writeup and job on this. We have implemented an extensive color selection via the customizer in a new theme but cannot seem to find a way to clear or reset. Does this functionality exist or can it easily be done? (There is no default tab on the color picker for peeps to revert to the default for some reason)

  9. Hey Otto,

    Is it possible to have multiple instances of these options, so that presets could be created for the user to choose from?

  10. […] For those interested in finding out more here is a link to a great article on “How to Leverage the Theme Customizer in your own Themes” […]

  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 the Ottopress.com website. […]

  12. Anyone have an issue with the controls not displaying in the order they are created? I can’t seem to find any common reason for their ordering and they seem to be different based on the order I declare them

  13. […] “squeeze” their options into the customizer, which is great. And there’s a great tutorial by Otto showing you how to do that. Thanks […]

  14. Excelent post, but how did you use saved customized settings? Do you need to create new method which will be used to generate css for example and put it in the header or what?


    add_action( 'wp_head', 'my_customized_style' );

    function my_customized_style()
    {
    echo (''.get_setting('setting_name').'');
    }

    ?

    • You use the settings the same way you used the same settings before. That bit doesn’t change.

      If you already had a settings page, then you must have already been using the settings in some fashion. This doesn’t affect that. In the next post, I go into how to make a theme without a settings page and using this and the theme_mod methods.

  15. I can see how this works to make an individual colour change, but what if you want one option to affect multiple changes in the css? E.g. option “blue” = dark blue h1 tags, light blue h2 tags and a white text on a blue background for the menu.

    • If your pre-existing option already does that, then it will just work without any special handling. The reload process will reload the page inserting your option in as if that was what it was already set to, so any PHP code you have to generate the color changes will take effect.

      If you’re wanting to make it “real-time” using postMessage, then you’d simply write your JS code so that it changes all the affected elements one by one.

      The JS I have for examples in the post only affect one thing each, but there’s no reason they can’t affect more than one thing. For example:

      	wp.customize( 'example_option', function( value ) {
      		value.bind( function( to ) {
      			if (to == 'blue') {
      				$('h1').css('color', 'blue');
      				$('h2').css('color', 'light-blue');
      				$('.menu').css('color', 'white');
      				$('.menu').css('background-color', 'blue');
      		});
      	});
      

      (Note, this code is an example, not necessarily working code. Fiddle with as needed.)

    • You would need 3 options for these, with a setting and control each, so one for the headings link color, one for the menu background, and one for the menu links. Then in your javascript section, you have three items for each defining the selectors, ie:

                      wp.customize('my_navigation_hover',function( value ) {
      			value.bind(function(to) {
      				jQuery('ul#nav li a').css({'color': to});
      			});
      		});
      

      When building your style.php, you can use multiple selectors at once per normal practice:

      h1, h2, h3{color:<?php echo get_option('my_title_color'); ?>;}
      
  16. Great post Otto, I got it working now!

    One thing I would like to change, but can’t figure out how and if it’s possible:

    – When closing the preview, we get a redirect to themes.php – is there anyway to redirect to another page (my theme options page)

    That would be great!

    Thanks, Sander

    P.S. If it’s not possible, I would also be happy to have an action_hook áfter the settings are saved. Now there’s only one before saving 🙁

  17. Hey Otto, great tutorial – I’ve used some of this in a theme I’m designing.

    I do have one question for you though: when using WP_Customize_Color_Control is there any way to go back to the original, default color (i.e. the one defined in the Theme’s stylesheet)?

  18. […] based on user selections. Otto has a couple of really good articles on how to use it. The first, How to leverage the Theme Customizer in your own themes, is a good introduction to the customizer. I was happy find that there’s even Javascript that […]

  19. Hey Otto,

    Great article thank you. I’m using serialized custom theme options, and it appears that when I add/hook-up custom checkbox fields, they work properly but ALWAYS load in the “checked” state, even though the HTML properly includes/doesn’t include the “checked” attribute…some JS appears to be automatically marking all them as checked, but I don’t have any custom scripts :/

    As I mentioned, they are hooked up to the underlying options properly, and checking and unchecking is reflected in preview-mode. Any ideas what might be causing this/what I’m doing wrong? I browsed the customize-base script, but nothing popped out…

    Thanks in advance!

  20. Cool, really cool. Looks like I miss a lot of new WP features.

  21. […] had a series of articles highlighting how to use the theme customizer in your WordPress themes instead of […]

  22. […] has been introduced in WordPress 3.4, and although Twenty Twelve doesn’t create its own custom settings in the customizer, it adapts very nicely to the existing ones, by setting their transport to postMessage and handling […]

  23. Otto, I was having trouble getting the real-time previewer to work (i.e. with ‘transport’ => ‘postMessage’). I tracked it down to this line:

    $('.posttitle').css('color', to ? '#' + to : '' );

    When echoing the color value out to the browser console it was appearing with a double ‘##’ prefixing the color value. So I just changed the code to the following which works fine:

    $('.posttitle').css('color', to );

    Should there definitely be a check in there for the ‘to’ value though? If so should it be something like this:

    $('.posttitle').css('color', to ? to : '' );

    • When I first wrote this, the color came out of the picker without the #. I believe they standardized it to behave differently in the final version, so the code may vary slightly from when I wrote this post.

  24. I understand how preview refresh when transport is postMessage and I used it successfull with some custom controls, but I don’t understad how preview iframe refresh when using default transport: if I use default transport with my custom controls I see the page refresh, but the nothing change. In twentyeleven, default transport is used eg. for color scheme option, but I can’t unserstand how there the preview change according to setting…

  25. HAve you notice how they have cleverly diasbaled links back to the admin URL in teh previewr, so you don’t go round in a ‘tunnel’ of links.

    But it is counter intuitive, as you view your site in preview / editor level, there are ‘edit page/post’ links onthe page – clicking on the link does not work, of course as it has been disabled, but that is counter intuitive, after all you are modifying your theme and then see some contnet in the previewer you want to change, so I think it would be nice to modify teh edit link in the previewer to save/close the previewer and go to edit page -or just fire up ‘target _blank’.

    What do you think? I’m not quite a javascript expert to be able to hack the core customizer code.

  26. I have successfully added a few color pickers to control various theme styles in real-time. Everything works great except when I try to use the customizer to update colors in real-time for hover styles!

    Anyone else tried to use the customizer to update color styles?

    Note: This works great even for hover styles when the transport is set to refresh, but when transport is set to postMessage it doesn’t work.

  27. Otto, looks like WP_Customize_Image_Control is not creating the uploaded images tab. Actually, it appears when I upload images without closing the Customizer. However, when closed, the tab is gone. Any thoughts on this?

  28. Rather than adding the chunk of JS in our footer for the real-time preview, can a script (a separate file) be enqueued with wp_enqueue_script() on customize_register? Seems to work for me, but I don’t know if I’m messing something else I haven’t found yet.

  29. Hi,

    I am getting something strange now on my theme, with twenty-eleven and the way I coded my thme options, if you change the background color, you get a smooth transition. But now I get a complete screen refresh (goes white for a second)when I select an item for change. Any one else experieneced this. I have tried to backtrack my code but can’t find the issue. Any clues would be helpful.

  30. I have a strange issue.

    I’ve created a colour selector for a #header { background: # } and linked it up to the one in my theme-options.php

    When I use the colour selector in customize and “update and save” the background goes blank (NULL) – if I then go to my theme options page, I can see the colour I just selected in customize in my theme options page.

    I then have to “save” on the theme options page for the colour to be added to the header background?

    I’m using a dynamic php stylesheet to carry the variables, otherwise there should be no difference from this tutorial

    my code for customise is as follows:

     add_action( 'customize_register', 'tcasino_customize_register' );
     
    function tcasino_customize_register($wp_customize) {
    	
    $wp_customize->add_section( 'tcasino_color_scheme', array(
        'title'          => __( 'Color Scheme', 'tcasino' ),
        'priority'       => 35,
    ) );
         
    $wp_customize->add_setting( 'tcasino_options[tcasino_hex_input]', array(
        'default'        => '000000',
        'type'           => 'option',
        'capability'     => 'edit_theme_options',
    	'transport'         => 'postMessage'
    ) );
    
    $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'tcasino_hex_input', array(
        'label'   => __( 'Site Color', 'tcasino' ),
        'section' => 'tcasino_color_scheme',
        'settings'   => 'tcasino_options[tcasino_hex_input]',
    ) ) );
         
    if ( $wp_customize->is_preview() && ! is_admin() )
        add_action( 'wp_footer', 'tcasino_customize_preview', 21);	 
    }
    function themename_customize_preview() {
        ?>
        <script type="text/javascript">
        ( function( $ ){
        wp.customize('tcasino_options[tcasino_hex_input]',function( value ) {
            value.bind(function(to) {
                $('#header').css('background-color', to ? '#' + to : '' );
            });
        });
        } )( jQuery )
        </script>
        <?php
    } 
    
  31. Hi,
    is there a way to choose which element inside a new section comes first?
    I tried to add the ‘priority thing’ to the setting part but… it doesn’t work.
    I have 8 different image upload that will be used for a slideshow but it shows up with apparently no sense…

    $wp_customize->add_section( 'camisud_slideshow' , array(
    		'title'      => __('Sezione Slideshow','camisud'),
    		'priority'   => 160,
    	) );
    	$defimage = get_template_directory().'/images/backisa.png';
    	$wp_customize->add_setting( 'cami_slide_1', array(
    		'default'    => $defimage,
    		'priority'   => 1,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_1', array(
    		'label'		 => __('Aggiungi Prima Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_1',
    	)));
    	  $wp_customize->add_setting( 'desc_slide_1', array(
            'default'        => 'descrizione',
    		'priority'   	 => 2,
        ) );
    	$wp_customize->add_control( 'desc_slide_1', array(
            'label'   => 'Inserisci la descrizione della prima immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_2', array(
    		'default'    => $defimage,
    		'priority'   => 3,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_2', array(
    		'label'		 => __('Aggiungi Seconda Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_2',
    	)));
    	  $wp_customize->add_setting( 'desc_slide_2', array(
            'default'        => 'descrizione',
    		'priority'   	 => 4,
        ) );
    	$wp_customize->add_control( 'desc_slide_2', array(
            'label'   => 'Inserisci la descrizione della seconda immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_3', array(
    		'default'    => $defimage,
    		'priority'   => 5,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_3', array(
    		'label'		 => __('Aggiungi Terza Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_3',
    	)));
    	$wp_customize->add_setting( 'desc_slide_3', array(
            'default'        => 'descrizione',
    		'priority'   	 => 6,
        ) );
    	$wp_customize->add_control( 'desc_slide_3', array(
            'label'   => 'Inserisci la descrizione della terza immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_4', array(
    		'default'    => $defimage,
    		'priority'   => 7,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_4', array(
    		'label'		 => __('Aggiungi Quarta Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_4',
    	)));
    	$wp_customize->add_setting( 'desc_slide_4', array(
            'default'        => 'descrizione',
    		'priority'   	 => 8,
        ) );
    	$wp_customize->add_control( 'desc_slide_4', array(
            'label'   => 'Inserisci la descrizione della quarta immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_5', array(
    		'default'    => $defimage,
    		'priority'	 => 9,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_5', array(
    		'label'		 => __('Aggiungi Quinta Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_5',
    	)));
    	$wp_customize->add_setting( 'desc_slide_5', array(
            'default'        => 'descrizione',
    		'priority'   	 => 10,
        ) );
    	$wp_customize->add_control( 'desc_slide_5', array(
            'label'   => 'Inserisci la descrizione della quinta immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_6', array(
    		'default'    => $defimage,
    		'priority'   => 11,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_6', array(
    		'label'		 => __('Aggiungi Sesta Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_6',
    	)));
    	$wp_customize->add_setting( 'desc_slide_6', array(
            'default'        => 'descrizione',
    		'priority'   	 => 12,
        ) );
    	$wp_customize->add_control( 'desc_slide_6', array(
            'label'   => 'Inserisci la descrizione della sesta immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_7', array(
    		'default'    => $defimage,
    		'priority'   => 13,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_7', array(
    		'label'		 => __('Aggiungi Settima Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_7',
    	)));
    	$wp_customize->add_setting( 'desc_slide_7', array(
            'default'        => 'descrizione',
    		'priority'   	 => 14,
        ) );
    	$wp_customize->add_control( 'desc_slide_7', array(
            'label'   => 'Inserisci la descrizione della settima immagine',
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'cami_slide_8', array(
    		'default'    => $defimage,
    		'priority'   => 15,
    	) );
    	$wp_customize->add_control( new WP_Customize_Image_Control($wp_customize, 'cami_slide_8', array(
    		'label'		 => __('Aggiungi Ottava Immagine','camisud'),
    		'section'	 => 'camisud_slideshow',
    		'settings'	 => 'cami_slide_8',
    	)));
    	$wp_customize->add_setting( 'desc_slide_8', array(
            'default'        => 'descrizione',
    		'priority'   	 => 16,
        ) );
    	$wp_customize->add_control( 'desc_slide_8', array(
            'label'   => "Inserisci la descrizione dell'ottava immagine",
            'section' => 'camisud_slideshow',
            'type'    => 'text',
        ) );
    	$wp_customize->add_setting( 'camisud_slider_chooser', array(
    		'default'    => 'value1',
    		'priority'   	 => 17,
    	) );
    	$wp_customize->add_control( 'camisud_slider_chooser', array(
        'label'      => __( 'Vuoi lo Slideshow o no?', 'camisud' ),
        'section'    => 'camisud_slideshow',
        'settings'   => 'camisud_slider_chooser',
        'type'       => 'radio',
        'choices'    => array(
            'value1' => 'Mostra SlideShow',
            'value2' => 'Nascondi SlideShow',
            ),
    	) );
    
  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. Great tutorial. Works great for me. One question I have is what would be the best way to add conditions to the customizer? I know the transport option only works for the preview pane, but could that function be used in the customizer itself? For example, if I choose “layout #1”, then I want a set of options to display for layout #1, or if I choose “layout #2”, I’d want a separate set of options to show up for that layout.

  34. Hey Otto & world… I’m utilizing the theme customizer from within a plugin which extends certain themes. Long story short, I have it working _perfectly._ Perfectly, that is, with one caveat:

    The user must have already used the plugin’s regular options panel to save some options (saved as a serialized array). Here’s what’s happening.

    If a user visits the Customizer prior to saving anything within the plugin’s distinct panels, then the Customizer only partially works. The options can be edited & even saved in the left panel, but despite the fact that the preview pane refreshes, it isn’t reflecting changes in the options.

    Saving the Customizer, and then refreshing the whole thing (or visiting the plugin panel) reveals that the options are in fact saved. Revisiting the Customizer after that, the live preview works fine.

    The plugin uses a couple of options, each a serialized array of a bunch of options related to “behind the scenes” features of a few themes. I’m hoping to avoid creating dummy, empty default options if at all possible, just to trick the Customizer into working as expected from the start.

    Any ideas on how to get around this?

  35. Thanks for this fantastic article! I’m wondering if it is possible to set required resolution and maximum height and width values – OR – to resize the file to the required dimensions and resolution upon upload with WP_Customize_Image_Control. Can you point me in the right direction?

  36. Yes John I am wondering the same thing to set resolution. Any answers to this one ?

  37. Thanks for the great article it really helped me out.

    But I’m stuck on one thing.
    I added a setting which changes the layout of a blogpost with or without a sidebar.
    This requires the site to reload for it to change the setting (just like the dark theme in your video) and can’t be done with javascript/post-message.

    The site does refresh but it doesn’t update the setting, if I hit save and publish it does update the setting.
    Is it possible to see this kind of settings in the live preview?

  38. I’ve added in a ‘select’ type but don’t know how to get the value of it to display on the front end of the site.


    // Hours: Monday
    $wp_customize->add_setting( 'open_mon', array(
    'default' => '09',
    ));
    $wp_customize->add_control( 'open_mon', array(
    'label' => 'Monday: Open',
    'section' => 'opening_hours',
    'type' => 'select',
    'choices' => array(
    '08' => '08:00AM',
    '09' => '09:00AM',
    '11' => '10:00AM',
    '12' => '11:00AM',
    '13' => '12:00PM',
    '14' => '1:00PM',
    ),
    ));

    Also don’t know how to display the value from dropdown-pages type.

  39. im using
    $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, ‘rdr_settings_image’, array(
    ‘label’ => ‘Profile Pic’,
    ‘section’ => ‘rdr_settings’,
    ‘settings’ => ‘rdr_settings_image’,
    ) ) );
    and retrieving it by
    get_theme_mod( ‘rdr_settings_image’ );

    but i can only get the full-size image, i want the thumb. How can i do that?

  40. […] 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. […]

  41. […] 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. […]

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

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

  44. Image uploads using original image rather then cropped image.
    How can i make sure system using cropped version?

  45. Just wondering.. Why can’t we click to a blogpost in the preview, to design (for example) the comment styling? When I click on a link nothing happens..

  46. Hi Otto, great work.

    I have never played with theme options before and this is my first try. I have one little problem that I fully don’t understand, and that’s how do I output the serialized settings.

    I have been trying this out, but the settings end up blank 🙁

    function roots_customize_css() {
    	?>
    	<style type="text/css">
    	 .navbar-inner { background-color:<?php echo get_theme_mod('roots_theme_options[nav_bg]'); ?>; }
    	</style>
    	<?php
    }
    
    add_action( 'wp_head', 'roots_customize_css');
    
    • The code “get_theme_mod(‘roots_theme_options[nav_bg]’);” doesn’t make any sense. Theme mod saved options are already specific to the theme, you don’t need extra array parameters around them.

      Without knowing how you’re referencing the options in the first place, I can’t give you an exact answer, but it should be something closer to get_theme_mod(‘nav_bg’). You’re not using serialized settings if you’re using theme mods, or rather, the serialization is hidden from you.

  47. […] few days after I published this, Otto on WordPress published a tutorial on using the Theme Customizer, which will be released with WordPress 3.4 before the end of the year. It’s great to see the […]

Leave a Reply to Kirk Wight Cancel 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=""> <s> <strike> <strong>

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