How to use Customize API “postMessage” Method for Color Options

customizer-color-option-postmesssage

I’m not actually a fan of themes with tons of design options. I think as a designer, it’s our job to design theme.

However, it’s not always a bad idea to let user express their creativity.

Last weekend, I create another theme. Nevertheless, a simple one with classic design. And this time I create several color options for it. Usually I prefer “refresh” transport method for my themes, because it’s works, easier to code (and maintain in the future). But because this is a simple theme, I get it done relatively quickly. So I decide to “play” and use “postMessage” transport method for the color options.

There are problems I found when implementing this, and I want to share my solution.

Here’s the theme, you can download and check the source code:

Register Customizer Settings

It’s relatively simple to do (if you are familiar with Customizer API), in this example I create two color option: “link color” and “site title” color option.

/* Color Options */
add_action( 'customize_register', 'my_color_customizer' );

/**
 * Register Customizer Setting
 * @since 1.0.0
 */
function my_color_customizer( $wp_customize ){

    /* === LINK COLOR === */

    /* Color setting */
    $wp_customize->add_setting( 'color_link', array(
        'default'             => '#ea7521',
        'transport'           => 'refresh',
    ));

    /* Add in color section */
    $wp_customize->add_control(
        new WP_Customize_Color_Control(
            $wp_customize,
            'color_link',
            array(
                'label'               => 'Link Color',
                'section'             => 'colors',
                'settings'            => 'color_link',
                'priority'            => 10,
            )
        )
    );

    /* === SITE TITLE COLOR === */

    /* Color setting */
    $wp_customize->add_setting( 'color_site_title', array(
        'default'             => '#ffffff',
        'transport'           => 'refresh',
    ));

    /* Add in color section */
    $wp_customize->add_control(
        new WP_Customize_Color_Control(
            $wp_customize,
            'color_site_title',
            array(
                'label'               => 'Site Title Color',
                'section'             => 'colors',
                'settings'            => 'color_site_title',
                'priority'            => 10,
            )
        )
    );

}

In the code above I use “refresh” post method. but we’ll change that to “postMessage” transport method later.

Implementation on front-end

To enable this option to modify color in front end, I simply print the CSS via wp_head hook:

/* Print CSS to wp_head */
add_action( 'wp_head', 'my_color_print_css' );

/**
 * Print BG Color CSS
 */
function my_color_print_css(){

    /* Var */
    $css = '';
    $color_link = get_theme_mod( 'color_link', 'ea7521' );
    $color_site_title = get_theme_mod( 'color_site_title', 'ffffff' );

    /* Link Color: Only if it's not the default. */
    if ( 'ea7521' != $color_link ){
        $css .= "a,a:hover,a:focus{color:#{$color_link}}";
    }

    /* Site Title Color */
    if ( 'ffffff' != $color_site_title ){
        $css .= "#site-title a,#site-title a:hover,#site-title a:focus{ color: #{$color_site_title}; }";
    }

    /* Print it. */
    if ( !empty( $css ) ){
        echo "\n" . '<style type="text/css" id="my-color-css">' . trim( $css ) . '</style>' . "\n";
    }
}

Now, we have a fully working color option using refresh transport method on the customizer and on the front-end. Easy-Peasy.

postMessage Transport Method

We simply need to change the code above from “refresh” to “postMessage”.

And when we change the color in the customizer setting, the preview won’t work. So we need to create a JS to handle the preview our self.

/* Customizer Preview JS */
add_action( 'customize_preview_init', 'my_customize_preview_js' );

/**
 * Preview JS
 * @since 1.0.0
 */
function my_customize_preview_js(){
    wp_enqueue_script( 'my-customizer-preview-color', get_template_directory_uri() . '/js/customizer-color.js', array( 'jquery', 'customize-preview' ), '0.1.0', true );
}

Preview JS

Using jQuery CSS to change the color

( function( $ ) {

    /* Link Color */
    wp.customize( 'color_link', function( value ) {
        value.bind( function( to ) {
            $( 'a,a:hover,a:focus' ).css( 'color', to );
        } );
    } );

    /* Site Title Color */
    wp.customize( 'color_site_title', function( value ) {
        value.bind( function( to ) {
            $( '#site-title a,#site-title a:hover,#site-title a:focus' ).css( 'color', to );
        } );
    } );
    
} )( jQuery );

Now everything should work correctly. Wrong!

In the front end it works fine (after we save the setting) but when we change the “Link Color” option in Customizer. It also change “Site Title” color. So “Link Color” option override all link color because it’s added directly as style attributes in all anchor link element.

The problem with the preview JS above is because the method to change the style from the “customizer preview” and the “front-end” implementation is different. That’s why we shouldn’t expect the same result.

We could exclude site title in our jQuery, but there’s …

A Better Solution

So the problem is, in the “customizer preview” we use jQuery CSS which will add style declaration in the element directly, and in the “front-end” we print style tag in the header (via wp_head).

So we just need to use the same method for consistency.

So this is how to do it:

#1. Create an empty style tag only in the customizer preview

/* Print CSS to wp_head */
add_action( 'wp_head', 'my_color_customizer_empty_style' );

/**
 * Print Empty Color CSS
 */
function my_color_customizer_empty_style(){

    /* Add in Customizer Only (style tag placeholder for link color). */
    global $wp_customize;
    if ( isset( $wp_customize ) ){
        echo "\n" . '<style type="text/css" id="my-link-color-css"></style>' . "\n";
        echo "\n" . '<style type="text/css" id="my-site-title-color-css"></style>' . "\n";
    }
}

So for each color option we need to create an empty style tag. And we are going to add the CSS inside that tag using Preview JS.

#2. Use Preview JS to modify that style tag.

It’s very simple to do, here’s an example code:

( function( $ ) {

    /* Link Color */
    wp.customize( 'color_link', function( value ) {
        value.bind( function( to ) {
            var color_link_css = 'a,a:hover,a:focus{color:' +  to + '}';
            $( '#my-link-color-css' ).html( color_link_css );
        } );
    } );

    /* Site Title Color */
    wp.customize( 'color_site_title', function( value ) {
        value.bind( function( to ) {
            var site_title_css = '#site-title a,#site-title a:hover,#site-title a:focus{color:' +  to + '}';
            $( '#nevertheless-site-title-color-css' ).html( site_title_css );
        } );
    } );
    
} )( jQuery );

And that’s it 🙂
Now we have a consistent, easy to use solution for postMessage transport method for color option.

Share if you think it’s useful or follow me on twitter (@turtlepod) for more tutorials like this.

Leave a Reply

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