1

I have a sticky header that has an initial background color and a different background color on scroll. I have javascript that adds a .navbar-scroll class to the following navbar upon scroll:

<nav id="nav" class="navbar navbar-fixed-top">
    ...
</nav>

The css looks like this:

.navbar {
    background-color: #000;
}

.navbar-scroll {
    background-color: #fff;
}

I have the following code in customizer.php:

// Header Background Color
$wp_customize->add_setting( 'header_background_color', array(
    'default'           => '#000',
    'transport'         => 'postMessage'
) ); 
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'header_background_color', array(
    'label'             => __( 'Header Background Color', 'my-theme' ),
    'section'           => 'title_tagline',
    'settings'          => 'header_background_color',
) ) );

// Sticky Header Background Color
$wp_customize->add_setting( 'sticky_header_background_color', array(
    'default'           => '#fff',
    'transport'         => 'postMessage'
) ); 
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'sticky_header_background_color', array(
    'label'             => __( 'Sticky Header Background Color', 'my-theme' ),
    'section'           => 'title_tagline',
    'settings'          => 'sticky_header_background_color',
) ) );

function header_output() {
    <style type="text/css">
    .navbar { 
        background-color: <?php echo get_theme_mod( 'header_background_color' , '#000' ); ?>;
    }
    .navbar-scroll { 
        background-color: <?php echo get_theme_mod( 'sticky_header_background_color' , '#fff' ); ?>;
    }
    </style>
} 
function generate_css( $selector, $style, $mod_name, $prefix='', $postfix='', $echo=true ) {
    ... // I'll omit this code here
}
add_action( 'wp_head' , 'header_output' );

I have the following code in customizer.js:

// Background Color
wp.customize( 'header_background_color', function( value ) {
    value.bind( function( newval ) {
        $('.navbar').css( 'background-color', newval );
    } );
} );

// Sticky Background Color
wp.customize( 'sticky_header_background_color', function( value ) {
    value.bind( function( newval ) {
        $('.navbar-scroll').css( 'background-color', newval );
    } );
} );

The problem I'm having is in the Customizer Live Preview. When the user changes either color, it injects the css style on that element and overwrites the existing style on that element. Therefore, the user can only see one color at a time. For example, if the initial Header Background Color is changed, that color will still be seen on scroll. If the Sticky Header Background Color is changed, only that color will be seen, whether user has scrolled or not. It will work fine on the front end once saved but I don't want to explain that bug to the user.

Is there a way to keep both styles active? Perhaps inject the css for each class in the head instead of inline?

0

Yes, instead of updating the inline style for the elements directly, a stylesheet should be used instead. You can create a stylesheet template that is used both in JS and in PHP. This was done in the Twenty Sixteen theme and I actually just worked on this in a standalone example plugin for another answer.

Notice how there is a stylesheet_template string that is created, and this template string is rendered out by PHP at the wp_print_styles action:

/**
 * Print styles.
 */
public function print_styles() {
    echo '<style id="wpse-286268" type="text/css">';
    $css = $this->stylesheet_template;
    $tpl_vars = array();
    foreach ( $this->device_configs as $slug => $params ) {
        $tpl_vars[ '{{outline_color_' . $slug . '}}' ] = get_theme_mod( "outline_color_{$slug}", $params['default'] );
    }
    echo esc_html( str_replace(
        array_keys( $tpl_vars ),
        array_values( $tpl_vars ),
        $css
    ) );
    echo '</style>';
}

And then also it is rendered out by JS in the customizer preview:

/**
 * Update preview.
 *
 * @returns {void}
 */
component.updatePreview = function updatePreview() {
    var css = component.stylesheetTemplate;
    _.each( component.deviceSettings, function( setting ) {
        css = css.replace( '{{' + setting.id + '}}', setting.get() );
    } );
    component.style.text( css );
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.