Been a while since I wrote something. Let’s talk about some of the new stuff available in the Customizer.

Forget about some of part two

First, back in part two, I had a bit about Surfacing the Customizer. That bit is outdated now, WordPress does this for you in later versions. So, yeah, skip that.

Shiny new thing: Panels

Okay, so Panels aren’t that new. They were added in WordPress 4.0. Basically, they’re sliding containers for sections. Having trouble fitting all your settings on the screen? Group the various sections up into Panels. Panels show up as an item in the main list, and when you click the arrow next to them, the whole list glides off screen to show only those sections.

So, now we have four things: Panels, Sections, Controls, and Settings.

All that’s new is a panel setting to tell the section to go into that panel. Simple.

Active Callbacks

One of the problems with the Customizer was that it displayed settings and showed them changing on the site to your right, but the site being displayed is the actual site. Meaning that you can navigate on it. Sometimes, the controls being shown don’t necessarily apply to the actual site that you’re seeing.

Example: If you have a control to change the color of something in the sidebar, but then are looking at a page which has no sidebar, then you have no visual feedback to tell you what the change looks like.

To fix this, “active callbacks” are used.

The active_callback is simply a new parameter that you can pass into Panels, Sections, or Controls. It can contain the name of a function, and that function will be called when the page changes. The function should return true or false (or equivalent) to indicate whether or not the element of the customizer should be shown for that page.

So, if you have a whole Panel that only make sense when the user is looking at Front Page of the site (and not an individual post), then you can do this:

And voila, when the user is not looking at the front page, the panel simply disappears.

You can use any of the normal WordPress Template Tags for this, or write your own function if you want to be more specific about it.

Edit: As pointed out in the comments, this will not work with ALL of the Template Tags. In particular, is_single won’t work because of the optional parameter it can take. You can define a wrapper for these methods instead, to get the same effect. Example:

Fun with Active Callbacks

If you do need to write your own callback function, note that the function receives the object in question when it’s called. So, if you attach an active_callback to a Panel, your function will get a argument of the WP_Customize_Panel object in question passed to it. Sections get WP_Customize_Section and such. You can use the information in these to decide whether the panel (or whatever) should be shown for that page.

So, how do we use that object? Well, you can use this to make whether certain controls show or not dependent on the values of other settings. All the various items you can use this on have a link back to the main WP_Customize_Manager. That class has a get_setting function, which you can use to determine what to do.

So, let’s make a control that causes other controls to appear, dependent on a setting.

Now, note that the callbacks are very similar. Seems like repeated code, doesn’t it? Well, it is, but remember that the $control here is the whole WP_Customize_Control object. We can use the same callback and simply check which control is calling it here instead.

So, instead of using two different callbacks, we just point our controls to this callback, which figures out what should show up for which setting. I’m sure you can simplify this further, depending on your particular needs.

One more thing: Customizing the Customizer

Not everybody likes the style of the Customizer. Maybe it clashes with your theme. Maybe you just want to tweak it a bit. Maybe you dislike that gray background color, and a more soothing blue would go better for your theme.

You can enqueue whole extra CSS files instead, if you like. Or, if you have special needs for javascript in some of your controls, and there’s libraries necessary to implement them, then you can enqueue those libraries here as well.

67 Comments

Ah…more cool things to play with. Now I will never get my themes finished, lol. Thanks Otto!
Anyway, I remember you replied to one of my comments at WPTavern in relation to the Customizer and said to let you know if there’s anything new I can suggest…well, here’s something I’ve been trying to find. How to change the radio inputs control to be images. For example, let’s say I have 8 layouts for the blog, each one is a radio button array.

Very informative post Otto!! I have been relying on a dedicated Theme Options page for my themes because WP Customizer always seemed counter-intuitive. One of my clients even termed it “tedious and confusing”. However, I have been reading more and more positive stuff about WP Customizer lately. I think now I am confident enough to use Customizer in my upcoming projects.

[…] “Otto” Wood, who has written several customizer articles over the years, wrote a “What’s new with the Customizer” tutorial that explores some of its newer features in depth, including panels, active […]

Hi Otto.
Thanks for your update of this series to the customizer.
I play currently with him, also for customization of front end topics, but not directly on the theme.
I have the problem, that I can’t change the url to the page, there I will customize via the Customizer.
I had play with add_query_arg(), but no result, that works. Also it is possible to parse via admin_menu hook the globals $submenu, $menu and change the url, like get_admin_url() . 'customize.php?url=' . wp_login_url() to customize the login url. But is not really clear and also in this topic after close the customizer I was logged out of the install.
Maybe you have a hint for me to create a url on click on a menu item in the Design Menu item?
Thanks a lot for the time.

Thanks for writing this up! I’ve recently been tasked with transitioning an older theme options implementation to using the Customizer API. Your posts have been extremely helpful in ramping up my knowledge — Thank You!

Quick question. I know that the default for the add_setting is for the customizer preview, not for the get_theme_mod, how do I set a default for get_theme_mod if its used in a if statement, for example in content.php For example:

The issue I am having is this: When someone activates my theme for the first time, in customizer view whatever is supposed to be shown by some_setting_name is being shown, however, if they look at the front of the site, nothing is being displayed where some_setting_name is suppose to display.

@dd, You can assign any section, default or not, to any panel you wish. This is very easy to do. I just created a panel and then I assigned it to that panel. Here is what I did, first I needed to find out what section the background color was initially assigned to. I did that by looking at this https://github.com/WordPress/WordPress/blob/master/wp-includes/class-wp-customize-manager.php, its located on lines 1395 through 1398. It states it is assigned to the colors section.

I created different color sections for my theme, i.e. one for sidebar colors, one for footer colors and so on and then assigned those sections to the Colors Section panel by adding this to each section:

'panel' => 'wpforge_colors',

I am now getting into adding active_callback – which is very very cool.

I try to undestand a bit better the active_callback paraemeter. As you stated we can use any WordPress Template Tag but when I try to use something different from is_front_page but nothing seems to work, neither a simple one as is_single.

That part may be incorrect. Not all template tags will work, because some of them accept parameters. The is_single function actually takes a post as the parameter, and so it can’t understand the control object being passed to the active_callback. You would need to write a wrapper function so as to have it ignore the parameter. Like `function callback_single() { return is_single(); }`, then pass that function to the active_callback instead.

Great article, I didn’t know the active callback functions received the control objects. I’ll have to do some refactoring to my themes.

But I do have a question, is it possible for for the active_callback parameter to receive a class? Similar to how the add_action function receives classes e.g. “add_action( ‘save_post’, array( $my_class, ‘save_posts_hook’ ) );”?

In the new Customizer I can see the Colors section, right under the Site Identity. And it’s empty. I already created a ‘Theme Colors’ section that uses the WP_Customize_Color_Control, and it works fine. Can I somehow use this default Colors section that appeared, or can I at least remove it somehow?

I like the look of the new Customizer, it’s really fast Also great tips in the article, I’ll be sure to use some

The Colors section is a default section in WordPress. It’s not empty, it contains the settings for the header text colors as well as the background colors when you have Custom Headers and Custom Backgrounds enabled.

And yes, you can put things in it instead of making your own Colors section. It’s just section=>’colors’.

Loving the ability to conditionally show/hide a setting based on the value of a different setting, but I notice a problem and I’m wondering if there is a work-around?

In my scenario, setting 1 is a radio button list and setting 2 (a checkbox) should only be shown if setting 1 is ‘large’. I use an “active_callback” to check if setting 2 should be shown, which works fine when I use “‘transport’ => ‘refresh'” for setting 1, but it fails when I use “‘transport’ => ‘postMessage'”.

I can see the logic as to why this would fail, so I’m looking for a way around it, such as calling the relevant “active_callback” through the “wp.customize” object, but I cannot find a way.

You can’t use active callbacks with postMessage, because the whole point of postMessage is to stop the refresh process. Since the PHP only executes when the refresh happens, then the two are fundamentally at odds.

Don’t use postMessage with active callbacks. It won’t work, for obvious reasons. There is no workaround. Just don’t even try it.

You can do it in JS. You just have to change the control’s active state via control.active.set( false ) (or true) depending on whether it is being made active or not. In other words, you can implement the same logic for the PHP active_callback in JS, like via the control’s ready method. I can share a working example if you like.

Yes, this is essentially correct. You can definitely add your own javascript to DIY it, but you won’t be doing it with the core active_callback mechanism.

Basically, if you want to use postMessage, then the entire process of updating the page content must be implemented in javascript. Since active_callback is for PHP functions, then it has no connection to postMessage. Switching to postMessage completely eliminates any calls back to the server for changes.

Just a quick question and I am not sure if this was covered above or not.

I have a setting in the customizer that allows the user to set an element to display either to the left or to the right. The default is Left. As of now the user can only see the change on refresh and I would like to show the change as soon as the user makes the selection.

I added everything necessary including ‘transport’ => ‘postMessage’ and so on, but when I try it nothing is happening. There is no screen refresh when Right is selected and the div does not switch to the right.

Just a quick question and I am not sure if this was covered above or not.

I have a setting in the customizer that allows the user to set an element to display either to the left or to the right. The default is Left. As of now the user can only see the change on refresh and I would like to show the change as soon as the user makes the selection.

I added everything necessary including ‘transport’ => ‘postMessage’ and so on, but when I try it nothing is happening. There is no screen refresh when Right is selected and the div does not switch to the right.

Hi Otto
i’m trying to add a section/panel inside the title_tagline section/panel – but it will not show- only displays in “root” of customizer – is it not possible to add a section/panel inside the defaults sections/panels?
I’ve tried using add_section and both: ‘panel’=>’title_tagline’ and ‘section’=>’title_tagline’ without luck
controls can be added to title_tagline just fine but not sections/panels

The “title_tagline” is a section and not a panel, so it cannot have a section nested inside. Sections cannot be nested inside other sections currently. Sections can either be in the root or inside of panels.

Hey Otto,
with the active callback you can show a section or panel depending on the URL you are looking at. But is it possible the other way arround? Showing a different URL depending on the section you have currently selected. Have been searching for hours for a way to do it. I know that you can change the previewURL with wp.customize.previewer.previewUrl but I wasn’t able to find how to bind this to the currently selected section/panel.

Not presently. A panel inside a panel is a section. But you cannot nest a section within a section currently. This was partly an intentional choice to prevent letting the UI get too deep. I believe there is a Trac ticket to discuss removing the limit.

[…] The parameter can take either the name of a function, or an anonymous function as long as it returns a truthy value. WordPress includes many conditional functions that you can use like my use of is_front_page above. You can do this with an entire section, or just an individual control. You can also base the context not on a page, but on the value of another control. Otto has a great example that I used during my talk, but you can read about it on his page. […]

I have a setting in the customizer that allows the user to set an element to display either to the left or to the right. The default is Left. As of now the user can only see the change on refresh and I would like to show the change as soon as the user makes the selection.

I added everything necessary including ‘transport’ => ‘postMessage’ and so on, but when I try it nothing is happening. There is no screen refresh when Right is selected and the div does not switch to the right. thaks