Image displaying various stars

Adding custom controls to your Customization API


In the last post, I talked about what the built in Customization API is and how to use it in your theme. Besides the built in customizer options like input fields, check boxes etc., there are few built in controls that you can use. But what if you want to enhance few of them, or add new ones? Then you’ll have to build your own.

In your customizer.php right before you add the function for setting up your custom control (or at the top of the file), you’ll need to add

require_once 'custom_controls.php';

This will call for the aforementioned file, that is in the same place where our customizer.php  is, where we’ll define our custom controls. In the js folder you can place custom_controls.js and in the css folder custom_controls.css . In those files we’ll add any css styling and custom JavaScript that we might need for our controls.

Essentially, we’re adding custom controls in our customizer.php  with this kind of code:

$wp_customize->add_control(new MY_NEW_Custom_control($wp_customize, 'control_name', array( /*labels and additional description goes here*/ )));

But for it to work, we need to extend the built in WP_Customize_Control class with our own. Then when we want to add it, we create a new object out of our control. This way you can reuse this code as many times as you want (yay for object-oriented programming :D).

Let’s get on with our custom controls. If you know all about the ins and outs of custom controls, and just want to see what controls I have so far, just head on to my git repository and download the files. I update it when I find out some new and cool controls.

Custom check box switch

In your custom_controls.php  file wrap the whole thing in

if (class_exists('WP_Customize_Control')){}

to avoid any errors if the customizer isn’t present. The first control that we’ll create is the custom check box. Regular check boxes can be a bit dull. Why not add a bit of life to them? The full code is

class Toggle_Checkbox_Custom_control extends WP_Customize_Control{ public $type = 'toogle_checkbox'; public function enqueue(){ wp_enqueue_style( 'custom_controls_css', get_template_directory_uri().'/inc/customizer/css/custom_controls.css'); } public function render_content(){ ?> <div class="checkbox_switch"> <div class="onoffswitch"> <input type="checkbox" id="<?php echo esc_attr($this->id); ?>" name="<?php echo esc_attr($this->id); ?>" class="onoffswitch-checkbox" value="<?php echo esc_attr( $this->value() ); ?>" <?php $this->link(); checked( $this->value() ); ?>> <label class="onoffswitch-label" for="<?php echo esc_attr($this->id); ?>"></label> </div> <span class="customize-control-title onoffswitch_label"><?php echo esc_html( $this->label ); ?></span> <p><?php echo wp_kses_post($this->description); ?></p> </div> <?php } }

So, we’ve created a Toggle_Checkbox_Custom_control . Inside each control we’ll enqueue our .js and .css files (if necessary). In our case we only need css, because we’re making styling changes after all. You’ll need to set up a type, and a method (a function) that will render your new control. In our case we’re added some additional wrappers to our check box. Remember, in the customizer.php we’re adding these controls by creating new objects. So $this will be a reference to that particular object. The usual object oriented approach. Now this is pretty straight forward. On to the css

.customize-control-checkbox label{ margin-left: 0; padding-top: 0; padding-bottom: 0; line-height: 28px; } .onoffswitch_label{ display: inline-block; vertical-align: top; margin-top: -1px; width: 200px; } .onoffswitch { position: relative; width: 40px; display: inline-block; float: right; -webkit-user-select:none; -moz-user-select:none; -ms-user-select: none; } .onoffswitch-checkbox { display: none!important; } .onoffswitch-label { display: block; overflow: hidden; cursor: pointer; height: 18px; padding: 0; line-height: 18px; border: 2px solid #9E9E9E; border-radius: 18px; background-color: #9E9E9E; transition: background-color 0.2s ease-in; } .onoffswitch-label:before { content: ""; display: block; width: 18px; margin: 0; background: #EBEBEB; position: absolute; top: 0; bottom: 0; right: 20px; border: 2px solid #9E9E9E; border-radius: 18px; transition: all 0.2s ease-in 0s; } .onoffswitch-checkbox:checked + .onoffswitch-label { background-color: #42A5F5; } .onoffswitch-checkbox:checked + .onoffswitch-label, .onoffswitch-checkbox:checked + .onoffswitch-label:before { border-color: #42A5F5; } .onoffswitch-checkbox:checked + .onoffswitch-label:before { right: 0; }

I’ve borrowed the css from this freebies page. Now all you need to do is to add the newly created control to your main file.

/** Custom Checkbox **/ $wp_customize->add_setting('custom_checkbox', array( 'default' => false, 'sanitize_callback' => 'mytheme_checkbox_sanitization', )); $wp_customize->add_control(new Toggle_Checkbox_Custom_control($wp_customize, 'custom_checkbox', array( 'label' => esc_html__('Check me', 'mytheme'), 'type' => 'checkbox', 'settings' => 'custom_checkbox', 'section' => 'section_custom_controls', )));
Custom checkbox control
Our newly styled checkbox. Much better than the regular boring one :D

Custom information control

Next control will be a simple one – information. Say you just want to put a small notice in your section about the next few controls. This control will give you the option to do so.

class Info_Custom_control extends WP_Customize_Control{ public $type = 'info'; public function render_content(){ ?> <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <p><?php echo wp_kses_post($this->description); ?></p> <?php } }

This one doesn’t need any css – it’s just text after all. Add your control and voila!

/** Info **/ $wp_customize->add_setting('custom_info', array( 'default' => '', 'sanitize_callback' => 'mytheme_text_sanitization', )); $wp_customize->add_control(new Info_Custom_control($wp_customize, 'custom_info', array( 'label' => esc_html__('A custom notice', 'mytheme'), 'description' => esc_html__('There are times that you just need to say something.', 'mytheme'), 'settings' => 'custom_info', 'section' => 'section_custom_controls', )));
Custom information control
Custom control when you want to add some kind of notice text

Separator control

Next one is also a simple one – a separator

/* Custom Separator */ class Separator_Custom_control extends WP_Customize_Control{ public $type = 'separator'; public function render_content(){ ?> <p><hr></p> <?php } }
/** Separator **/ $wp_customize->add_setting('separator_1', array( 'default' => '', 'sanitize_callback' => 'esc_html', )); $wp_customize->add_control(new Separator_Custom_control($wp_customize, 'separator_1', array( 'settings' => 'separator_1', 'section' => 'section_custom_controls', )));
custom separator control
You never know when you’ll need a separator

Multi input field

The next control is a multiple input field. Basically a type of repeater, when you need to add a list or what ever you might need (in the themes I was working on we used this to add new sidebars).

/* Multi Input field */ class Multi_Input_Custom_control extends WP_Customize_Control{ public $type = 'multi_input'; public function enqueue(){ wp_enqueue_script( 'custom_controls', get_template_directory_uri().'/inc/customizer/js/custom_controls.js', array( 'jquery' ),'', true ); wp_enqueue_style( 'custom_controls_css', get_template_directory_uri().'/inc/customizer/css/custom_controls.css'); } public function render_content(){ ?> <label class="customize_multi_input"> <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <p><?php echo wp_kses_post($this->description); ?></p> <input type="hidden" id="<?php echo esc_attr($this->id); ?>" name="<?php echo esc_attr($this->id); ?>" value="<?php echo esc_attr($this->value()); ?>" class="customize_multi_value_field" data-customize-setting-link="<?php echo esc_attr($this->id); ?>"/> <div class="customize_multi_fields"> <div class="set"> <input type="text" value="" class="customize_multi_single_field"/> <a href="#" class="customize_multi_remove_field">X</a> </div> </div> <a href="#" class="button button-primary customize_multi_add_field"><?php esc_attr_e('Add More', 'mytheme') ?></a> </label> <?php } }

For this control you’ll need some JavaScript

jQuery(document).ready(function($) { "use strict"; // ************* Multi_Input_Custom_control ********************* function customize_multi_write($element){ var customize_multi_val = ''; $element.find('.customize_multi_fields .customize_multi_single_field').each(function(){ customize_multi_val += $(this).val()+'|'; }); $element.find('.customize_multi_value_field').val(customize_multi_val.slice(0, -1)).change(); } function customize_multi_add_field(e){ e.preventDefault(); var $control = $(this).parents('.customize_multi_input'); $control.find('.customize_multi_fields').append('<div class="set"><input type="text" value="" class="customize_multi_single_field" /><a href="#" class="customize_multi_remove_field">X</a></div>'); } function customize_multi_single_field() { var $control = $(this).parents('.customize_multi_input'); customize_multi_write($control); } function customize_multi_remove_field(e){ e.preventDefault(); var $this = $(this); var $control = $this.parents('.customize_multi_input'); $this.parent().remove(); customize_multi_write($control); } $(document).on('click', '.customize_multi_add_field', customize_multi_add_field) .on('keyup', '.customize_multi_single_field', customize_multi_single_field) .on('click', '.customize_multi_remove_field', customize_multi_remove_field); $('.customize_multi_input').each(function(){ var $this = $(this); var multi_saved_value = $this.find('.customize_multi_value_field').val(); if(multi_saved_value.length>0){ var multi_saved_values = multi_saved_value.split("|"); $this.find('.customize_multi_fields').empty(); $.each(multi_saved_values, function( index, value ) { $this.find('.customize_multi_fields').append('<div class="set"><input type="text" value="'+value+'" class="customize_multi_single_field" /><a href="#" class="customize_multi_remove_field">X</a></div>'); }); } }); // ************* Multi_Input_Custom_control END ********************* });

Basically adding, removing and writing to our custom control. In your customizer.php you’ll add

/** Multiple input field **/ $wp_customize->add_setting('multi_field', array( 'default' => '', 'transport' => 'postMessage', 'sanitize_callback' => 'mytheme_text_sanitization', )); $wp_customize->add_control(new Multi_Input_Custom_control($wp_customize, 'multi_field', array( 'label' => esc_html__('Multiple inputs', 'mytheme'), 'description' => esc_html__('Add more and more and more...', 'mytheme'), 'settings' => 'multi_field', 'section' => 'section_custom_controls', )));
Multiple input control field
Multi input custom control – you can add any kind of text here that can be used in a different ways

Sidebar drop down control

This control comes in handy when you want to define which sidebar will go with certain page/blog layout. In my case I used it when I wanted to separate shop pages sidebar from single product page sidebar, so you can add this control to choose which one you’ll use on certain page.

/* Sidebar Dropdown field */ class Sidebar_Dropdown_Custom_Control extends WP_Customize_Control{ public $type = 'sidebar_dropdown'; public function render_content(){ ?> <label class="customize_dropdown_input"> <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <p><?php echo wp_kses_post($this->description); ?></p> <?php global $wp_registered_sidebars; ?> <select id="<?php echo esc_attr($this->id); ?>" name="<?php echo esc_attr($this->id); ?>" data-customize-setting-link="<?php echo esc_attr($this->id); ?>"> <?php $sidebar_shop = $wp_registered_sidebars; if(is_array($sidebar_shop) && !empty($sidebar_shop)){ foreach($sidebar_shop as $sidebar){ echo '<option value="'.$sidebar['name'].'" ' . selected( $this->value(), $sidebar['name'], false ) . '>'.$sidebar['name'].'</option>'; } } ?> </select> <br> </label> <?php } }

And adding the control is

/** Sidebar dropdown **/ $wp_customize->add_setting('sidebar_dropdown', array( 'default' => '', 'sanitize_callback' => 'mytheme_text_sanitization', )); $wp_customize->add_control(new Sidebar_Dropdown_Custom_Control($wp_customize, 'sidebar_dropdown', array( 'label' => esc_html__('Sidebars', 'mytheme'), 'description' => esc_html__('Choose sidebar for the page you specify', 'mytheme'), 'settings' => 'sidebar_dropdown', 'section' => 'section_custom_controls', ))); 
Sidebar drop down control
Sidebar drop down control

This is kind of a variation on built in ‘dropdown-pages’ type control, just with sidebars. You could do the same for categories, custom taxonomies etc. Just tweak the code a bit.

Image radio buttons

The last custom control I’ll add is the image radio buttons. Now this one is a bit different, because you’ll need to include the images for your image select. This is basically radio button re-vamped, kinda like what we did with the check box. This control is a good way to give user a ‘preview’ of sorts. Remember how they say that the image is worth a thousand words? Well that’s absolutely true. When the user sees a radio button for, let’s say layout style in a shop, he only has a written descriptions that should be as concise as possible. Layout right or sidebar right is kinda dry. But if he sees a little image with what the layout can look like, he gets the picture (no pun intended :D). So on to our custom control

/* You need to include the images you want to select. Add as many as you want to. In this example there are 3 images, that are supposed to go in 3 columns in one row.*/ class Image_Select_Custom_Control extends WP_Customize_Control{ public $type = 'image_select'; public function enqueue(){ wp_enqueue_style( 'custom_controls_css', get_template_directory_uri().'/inc/customizer/css/custom_controls.css'); } public function render_content(){ ?> <div class="customize_image_select"> <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span> <p><?php echo wp_kses_post($this->description); ?></p> <label> <input type="radio" name="<?php echo esc_attr($this->id); ?>" value="1" data-customize-setting-link="<?php echo esc_attr($this->id); ?>" <?php checked('1', esc_attr($this->value()) );?>/> <img src="<?php echo get_template_directory_uri().'/images/image_1.png'?>" alt="<?php esc_attr_e('Option 1', 'mytheme'); ?>" title="<?php esc_attr_e('Option 1', 'mytheme'); ?>" /> </label> <label> <input type="radio" name="<?php echo esc_attr($this->id); ?>" value="2" data-customize-setting-link="<?php echo esc_attr($this->id); ?>" <?php checked('2', esc_attr($this->value()) );?>/> <img src="<?php echo get_template_directory_uri().'/images/image_2.png'?>" alt="<?php esc_attr_e('Option 2', 'mytheme'); ?>" title="<?php esc_attr_e('Option 2', 'mytheme'); ?>" /> </label> <label> <input type="radio" name="<?php echo esc_attr($this->id); ?>" value="3" data-customize-setting-link="<?php echo esc_attr($this->id); ?>" <?php checked('3', esc_attr($this->value()) );?>/> <img src="<?php echo get_template_directory_uri().'/images/image_3.png'?>" alt="<?php esc_attr_e('Option 3', 'mytheme'); ?>" title="<?php esc_attr_e('Option 3', 'mytheme'); ?>" /> </label> </div> <?php } }


/** Image control **/ $wp_customize->add_setting('image_options', array( 'default' => '2', 'sanitize_callback' => 'mytheme_text_sanitization', )); $wp_customize->add_control(new Image_Select_Custom_Control($wp_customize, 'image_options', array( 'label' => esc_attr__( 'Layout', 'mytheme' ), 'description' => esc_attr__( 'Choose the layout for your blog', 'mytheme' ), 'settings' => 'image_options', 'section' => 'section_custom_controls', ))); 

And of course, the styling

.customize_image_select label{ display: inline-block; margin-right: 3px; margin-bottom: 5px; } .customize_image_select label:last-of-type{ margin-right: 0; } .customize_image_select label input{ display:none; } .customize_image_select label input + img{ border-color: #d3dad7; border-width: 3px; border-style: solid; } .customize_image_select label input:checked + img{ border-color: #0074a2; border-width: 3px; border-style: solid; }

And you have yourself a cool image radio box to choose

Image radio buttons
Image radio buttons. Much better than the old ones.

And this is it so far. There are others interesting controls out there to add, like Google Fonts one – a colleague of mine created this control, so I’ll need to see how to add it myself first before adding that to my git repo. The Google Fonts is a bit tricky, because you need to add the API key for it, so that you can get a list of all the google fonts. But you can really add what ever kind of control that you can think of.

Implementation of these controls is the same as with the other ones – get_theme_mod().

I hope this was an interesting tutorial, if you have a comment or a question, leave it below :)

Help spreading the word


  1. David Morgan



    This is awesome! Thanks! :)

  2. Ben Sibley



    Thanks so much for publishing this. I was trying to figure out a good way to add repeating fields to the Customizer. The method here is quite clever ;) Just made use of it in a new theme.

  3. Karlo



    Great post Denis! Do you think that Multiple input fields could be used to dynamically generate page sections for example on One-Page style themes or did you maybe came across a solution for dynamically adding wp customizer sections per user input? Pozdrav :)

    • Denis Žoljom



      What comes to mind is to use the multiple input fields and change input to page dropdown, or posts dropdown. Then in each page you could create some content, then use customizer
      to order the pages and then show that customizer field on a page template to render content from these fields like described here: A bit complicated but it’s possible. This would also save any content on theme switch, which is a requirement on themes :) You could also make them sortable so that you can reorder those easily.

      • Karlo



        Thanks for quick replay :) Actually I was thinking about to use this approach, saw a couple of themes using it, It does the job done just a bit more time consuming. Maybe it would be better to use SiteOrigin builder instead, saw org themes using it just not sure how theme reviewers will react. Thanks for response and maybe we’ll see each other on WordCamp Zagreb, if so the beer is on me :)

        • Denis Žoljom



          I don’t think that you can bundle SiteOrigin’s builder in the theme, but you can recommend it (using TGM plugin). I’m giving a talk on WordCamp Zagreb so feel free to talk to me afterwards :D

  4. mt



    Thank you for your information.
    So I have a question: When you say “For this control you’ll need some JavaScript” in the part of Multi input field, in what file do you add the code to?

  5. sonia maklouf



    Hi Denis I read both of your tuto on customization api. And I found them great so I decided to go further and to read some other tuto about customizer and I found this
    They’re saying ‘Customizer options can be granted to users with different capabilities on a granular basis’ and they’re giving an example at the end in

    Allow Non-administrators to Access the Customizer but I didn’t understand there example.

    For example if I had a portfolio site of photograph and I want each photograph being able to choose the layout of his presentation page with your radio button. I want the photograph to only have access to the photograph section. How could I do this ? To sum up how could I give to some user the capacity to see some section according to their user role.
    I find my example a little bit tricky but I think you understand what I mean :)

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.