The WordPress Customizer and Checkboxes


While working with checkbox inputs in the Customizer, I discovered an inconsistency with the values that were being returned to my plugin using the get_option  function. Please note that WordPress saves checkbox values in the options table as either “1” or “” for checked and unchecked respectively. Below are some of the scenarios that I encountered.

Scenario #1

In the Customizer, the checkbox is initially unchecked and the value is “”. I check the checkbox, the page refreshes and shows a value of TRUE. I toggle the checkbox and the value changes from TRUE (for checked) and FALSE (for unchecked). I save the settings with the checkbox checked and exit the customizer. The value is now “1”.

Scenario #2

With a value of “1”, I enter the Customizer. The value changes to TRUE and the checkbox is already checked. I uncheck the checkbox and the value changes to “1”. I check the checkbox again and the value changes to TRUE. Both checked and unchecked values are TRUE and “1” respectively.

In these two scenarios, while in the Customizer, checked values are returned as either TRUE or “1” and unchecked values are returned as either FALSE, “”, or “1”. Because of that, it’s impossible to know for sure the true state of the checkbox.

Fortunately, I was able to create a workaround by using the sanitize_callback  property when adding the settings, like so:

$wp_customize->add_setting( 'my_setting', array(
    'type' => 'option',
    'transport' => 'refresh',
    'sanitize_callback' => 'my_customizer_sanitize_checkbox',
    'default' => '1',
) );

And here is the code for the callback:

function my_customizer_sanitize_checkbox( $input ) {
    if ( $input === true || $input === '1' ) {
        return '1';
    return '';

After that, I had no more problems. Checked checkboxes were consistently “1” and unchecked checkboxes were consistently “”. I didn’t find much information when searching for this, so I hope that this information will be helpful to someone.

There appears to be a ticket in trac about this issue from two years ago: