How to Add Customizer Panels, Sections & Controls

Child Theming, Extension Development

Last Updated: for: 1.5.4 Time to Read: 10 minutes

WordPress Customizer Controls are the form elements that you see inside the WordPress Customizer which provide options such as color pickers, layouts, styling and widget area selectors . These Controls get assigned to accordion-like groups for organization (panels), making it easier for user to find the options they want.

Customizer controls may be added in both Extensions and Child Themes. The following assumes you have already setup your Child Theme or Layers Extension and are at the point where you are adding custom functions.

You may add defaults for the pre-existing Layers controls via the layers_customizer_control_defaults hook as described in the Styling section of this guide. This is recommended in Child Themes where you need to reset the default color controls to ensure your CSS is honored. Click the hook link above to view detailed instructions.

To understand where your customizations will appear, and which element you need to add, the following illustrates the terms we use:


  1. Panel
  2. Section
  3. Control
  4. Option

The first tier, high level, groups are know as Panels, and those inside them are called Sections, and finally those open up to reveal the Controls containing all the options. WordPress allows theme and plugin developers to add sections and panels using the add_section()   function. Controls are then added to these sections by first registering a ‘theme_mod’ type setting using add_setting()  and then assigning the setting to a Control using add_control()   that will decide how the setting is presented to the user.

We make this process easier by providing a set of filters and keys for building custom controls in a more efficient way.

You can choose to add custom panels to house your new sections and controls, or you can add sections to existing panels or controls to existing sections. Adding to our config array will neatly initialize your controls at the same time the Layers controls are initialized.


You first need to create a custom class to hold your controls inside a new file which we call controls.php.This class is setup just like the main plugin class.

Include this file from inside your main plugin class __construct() or init() function with a simple require_once():

Back to your controls class, setup a handful of helper filters for the panels, sections and controls inside your constructor or initializer. For demonstration we will use init() here so you can see the (small) difference between init() and __construct(). These filters can be used as shown here.


The corresponding functions are added along with other public functions in your main plugin class, after the init() function, explained in more detail below.

Child Theme

Your custom controls function in a child theme opens almost identically to an extension, but does not need to define public visibility.

The filter and custom function containing your controls can go into the child theme’s functions.php and requires a unique callback


The following explains each function in detail and how to format it based on whether you are adding new or adding to.

Reference: layers_customizer_panels


Child Theme

  • Line 1: Safety condition ensures a conflict does not occur if a function with the same name is already run. Choosing unique function names helps avoid this too.
  • Line 2: setup your function to modify the $panels index.
  • Line 3: Set the key or name for your panel, ie ‘mytheme-theme-options’. These should be lower-case and use only – or _ to separate words.
  • Line 4: Set the ‘title’ for your section that displays in the Customizer. Strings should always use l10n methods, ie
    __('string', 'textdomain')
  • Line 5: Set the ‘description’ (optional). This is a short bit of text you can use as instruction or clarification.
  • Line 6: Set the ‘priority’ which is a numeric value that determines where the panel sits sin the list. 130 is a safe choice as it ensures your panel loads below and after the core Layers panels.

Reference: layers_customizer_sections


The panel  value corresponds to the $panels  key, set in the above section as demoextension . If you are not creating a custom panel, then this would be a layers panel ID (see the linked reference above)

Child Theme

Each section should define a title  and the panel  it will be added to. This example shows how you would add a custom section called header-social-media   (Social Media Profiles) to our custom panel called demoextension   (Demo Extension)

Adding Sections to Existing Panels

This example shows how you would add our custom section called header-social-media    (Social Media Profiles) to the existing Header ( header ) panel in Layers. The primary difference here is the array_merge  which takes your section and merges it with the existing ones. You must merge on existing panels, whereas you don’t if using a custom panel.

The following panels are created by Layers:

Panel: Site Settings
Panel: Header
Panel: Blog

Panel: Footer
Panel: WooCommerce
You can also add custom sections to existing non-Layers panels like the default WordPress panels using the WordPress Core API instead of the Layers filters.

Reference: layers_customizer_controls


In our extension tutorial, we create a custom post type and add a few custom fields to it like a Credit Name, URL and Photo description. Our custom controls will add the option to show or hide this meta on single posts using our post type, in addition to basic meta like the date or sidebars.

The important bit here is the array merge, which takes these custom controls and adds them to the overall controls array for loading.

Each control group uses an array to define itself, ie demo-post-options . At a minimum you need a type   and label   within each individual option.

Child Theme

This example shows how you would add some text fields for entering Social Network URLs in the custom section header-social-media referenced in our custom section above:

$controls [‘section-name’] = In our example, our section is called header-social-media . Each option sets up its own array that must have a title and label.


Defines the type of control.

See layers_customizer_controls for a list of available types


The title. This should use l10n method
to wrap the value


Used in combination with a type of layers-text , layers-textarea , layers-rte  or layers-code  element, and sets some default text inside the field to use an example or instructions.


Long-form text describing what your control is used for (optional). Descriptions should be formatted with sprintf and use l10n


Used in combination with a select type to define the drop-down options. The below example shows how we add a Widget Areas option using the layers-select type and populate the drop-down with 0-4 using choices.

Adding Controls to Existing Sections

In the above example we set the section name in the $controls array, then return $controls. When adding controls to an existing section, we need to use an array_merge before returning the $controls to set the section.

You can reference the available key names for the Layers Sections  in the $controls  array in core/customizer/config.php

In the following example, we setup a custom controls array $social_media_controls , then merge it with the $controls array in the header-layout section. See how the syntax varies slightly:

The following Panels and Sections already exist in Layers, which can be extended by adding your custom controls to the relevant section where header-layout is used in the above example:

  • Panel: Site Settings
    • Section: Logo & Title
    • Section: Navigation
    • Section: Site Colors
    • Section: Sidebars
    • Section: Fonts
  • Panel: Header
    • Section: Layout
    • Section: Additional Scripts
  • Panel: Footer
    • Section: Layout
    • Section: Customization
    • Section: Text
    • Section: Additional Scripts
  • Panel: WooCommerce

WordPress offers the following defaults:

  • title_tagline – Site Title & Tagline
  • colors – Colors
  • header_image – Header Image
  • background_image – Background Image
  • nav – Navigation
  • static_front_page – Static Front Page

You can also add custom controls to existing non-Layers sections like the default WordPress sections  using the WordPress Core API instead of the Layers filters.

This should give you an idea of the general format of a control, and for more examples you can have a look in core/customizer/config.php where you’ll see all the controls that we initialize in Layers.

We do not recommend doing this in commercial prodicts. See layers_remove_config_element() for details on how to use this filter when necessary.

If you have setup a custom control with a type of layers-color  , you will need to link it to the element it needs to modify, then output the CSS correctly using layers_inline_styles . This ensures the customizer option overrides everything else, absolutely. It also allows you to tap into the invert control that helps text elements adjust automatically depending on if the user chooses a light or dark background color. This can help you set shortcuts and cut down on the number of color controls.

You can see how we do this for the default color controls in core/helpers/template.php inside the layers_apply_customizer_styles() function.

The first value wp_enqueue_scripts allows you to hook your function into the pre-existing lineup of scripts and let’s WordPress manage when the script fires and where in the source it is output. The second value defines your function name and the third is the priority. 100 is a safe number and is more important to plugin authors.

  • Line 1-2 : The above example creates a new function
  • Line 3: Set up a variable
    that will represent the user’s choice. We use
    to grab our custom control
    defined on line 4 (assuming we created one with this key name using the above Custom Control methods)
  • Line 5:TRUE corresponds to$allow_empty  and should always be true for colors, so don’t worry about that!
  • Line 7:  A condition to ensure the option is set. If it is blank, no inline CSS will be output.
  • Line 8: Finally, we setup our inline css using layers_inline_styles()

This code goes in your theme’s functions.php or inside your plugin’s class where all other custom hooks go, NOT inside your custom controls, sections or panels functions!

To utilize a setting in the front end on Layers, we use a helper function called layers_get_theme_mod()  which works just like the WordPress core get_option().


Each $option  for layers_get_theme_mod($option)  is the custom option name you setup in your custom controls array. This example shows how we would use a condition to determine whether a sidebar is added to the demo post view depending on the option choice.


Child Theme

In the following example we will add some social icons, corresponding to the networks set in these options, to the header of Layers using the layers_after_logo hook. This goes into your functons.php or plugin class where all other hooks are set.