That was actually a question by a fellow WordPress designer/developer when he realized his code didn’t work (I’ll explain the problem below).
It’s actually a simple mistake and can be avoided if we use “refresh” transport method when creating customizer option. But I do understand that “postMessage” transport method is better (but needed more code).
So here’s a little example. I create a twentyfifteen child theme with customizer setting to hide/show header area.
With very little code we can create that setting:
/* Customize Register */ add_action( 'customize_register', 'my_customize_reg' ); /** * Create Customizer Setting */ function my_customize_reg( $wp_customize ){ /* Setting */ $wp_customize->add_setting( 'hide_header', array( 'default' => 0, )); /* Control */ $wp_customize->add_control( 'hide_header', array( 'label' => 'Hide Header (masthead)', 'section' => 'title_tagline', 'settings' => 'hide_header', 'type' => 'checkbox', 'priority' => 40, )); }
And we need to modify/override “header.php” template from child theme too. We simply need to wrap the #masthead
element with this code:
<?php if( ! get_theme_mod( 'hide_header' ) ) : ?> <?php /* HEADER HTML HERE */ ?> <?php endif; ?>
Now we have a fully working customize setting using refresh transport method.
No problem. Easy Peasy.
But How to use postMessage Transport Method?
Change the transport method
/* Setting */ $wp_customize->add_setting( 'hide_header', array( 'default' => 0, 'transport' => 'postMessage' ));
After defining the transport method in add_setting()
, now the live preview will not refresh and update it self. Now we need to create a JS file to handle updating the preview ourself.
Customizer JS
/* Customize Script */ add_action( 'customize_preview_init', 'my_customize_script' ); /* Customizer: Enqueue Script */ function my_customize_script(){ wp_enqueue_script( 'my-customizer-js', get_stylesheet_directory_uri() . '/js/customizer.js', array( 'jquery', 'customize-preview' ), '0.1.0', true ); }
Create a customizer.js in “js” folder in child theme, and we are ready to go. This JS script will only load on customizer live preview.
JS Code
( function($) { /* Hide/Show Header */ wp.customize( 'hide_header', function( value ) { value.bind( function( to ) { if( to ){ $( '#masthead' ).hide(); } else{ $( '#masthead' ).show(); } }); }); })(jQuery);
As you can see, the code is pretty straight-forward: If “hide_header” setting is checked, hide the #masthead
element, if unchecked, show it.
The Problem
#1. Check the checkbox to hide the header
#2. Exit customizer (or refresh/f5)
#3. Back to customizer and uncheck to show header
#4. It won’t show the header!
Now here’s the problem with the code above. Remember the template code in header.php to show/hide masthead element:
<?php if( ! get_theme_mod( 'hide_header' ) ) : ?> <?php /* HEADER HTML HERE */ ?> <?php endif; ?>
The code above will not load #masthead
header element at all. And this will make our JS code cannot show it.
You cannot show/hide element not exist in the DOM. right?
So the JS to handle the live preview is fine, what’s wrong is with the implementation of the setting in the template file.
How to Fix
It’s easy fix. Just remove the template conditional to load/not load the #masthead header element above, and simply show/hide using CSS like so:
Create a body class so we can show/hide header using CSS
I really like dynamic classes in WP. And we are going to use that:
/* Body Class */ add_filter( 'body_class', 'my_body_class' ); /* Add Body Class */ function my_body_class( $classes ){ if( get_theme_mod( 'hide_header' ) ){ $classes[] = 'hide_header'; } return $classes; }
The code above will add hide_header
body class if the option is checked.
Note: You can also show/hide by printing the CSS via wp_head
hook.
Hide/Show #masthead using CSS
Using the custom body class above we now can hide header using CSS:
/* Hide Header */ .hide_header #masthead{ display: none; }
Awesome! now we have a full code. All works correctly now.
I still don’t want to load the element.
Sometimes, using CSS method to show/hide element is not the right solution. What if, we simply don’t want to load the element but still want to use “postMessage” transport method?
It’s actually very simple. We can check if we are in customizer live preview and load that element all time and conditionally load element on the front-end.
to check if we are on the customizer live preview we can check if the global $wp_customize
is set/not in the template.
Simply change the code in header.php to this:
<?php if( isset( $GLOBALS['wp_customize'] ) || ! get_theme_mod( 'hide_header' ) ) : ?> <?php /* HEADER HTML HERE */ ?> <?php endif; ?>
Now finally we have full working customizer setting to hide/show element using postMessage
transport method.
You can download the child theme example here:
Happy coding 🙂
Thanks for this tutorial. It was definitely helpful.