Jason G. Designs

WordPress Themes, Design Tutorials, Linux Themes and more…

How to Integrate High Definition Images into WordPress’s Custom Background

Pink flower high definition vs. regular image
Pink flower high definition vs. regular image

Background flower image is courtesy of pixabay.

In the course of updating Urban Square, I noticed the theme’s high definition background did not match with the options for WordPress’s built in custom background feature. For instance, in the captioned screenshot below, you can see that the custom background gives you several alignment and repeat options.

WordPress's Custom Background CSS options

WordPress’s Custom Background CSS options.

The way I had the high definition equivalent set up, users would simply drop in a 2x sized image to be swapped in on high definition displays. Simple enough. The problem is that the high definition version would just be one single image that stays in place, while the non hd version would change alignment, tile, etc. Not good. So, I had to come up with a new way forward.

Luckily, while researching, I landed on this Envato Tuts+ article linked from a Stack Overflow page: Modifying Custom Background Feature for Any HTML Element You Want. In this article, the author figured out where the code that creates the custom background feature is in the core files and how to filter its CSS stylesheet on the front end. I thought that this can be used to match our high definition image output to its non-hd counterpart.

This tutorial is recommended for readers familiar with setting up Customizer settings and controls, as well as how to include files into functions.php.

Setting up our Customizer controls

In my theme, I have a High Definition section, where users can upload a matching background image at twice the pixel resolution. Alternatively, you can add this to the existing Header Image section. Here is the way to do both.

In functions.php or a file included in functions.php, add:

$wp_customize->add_section(
	'themeslug_hidef', array(
		'title' => __( 'High Definition', 'text-domain' ),
		'description' => __( 'Upload a high definition version of your background image at twice the horizontal and vertical resolutions', 'text-domain' ),
		'priority' => 85,
	)
);

$wp_customize->add_setting(
	'background_2xbg_upload',
	array(
		'sanitize_callback' => 'esc_url_raw'
	)
);

$wp_customize->add_control(
	new WP_Customize_Image_Control(
		$wp_customize, 'background_2xbg_upload', array(
			'label' => __( 'Current @2x Background', 'text-domain' ),
			'section' => 'themeslug_hidef',
			'settings' => 'background_2xbg_upload'
		)
	)
);

or, alternatively:

$wp_customize->add_setting(
	'background_2xbg_upload',
	array(
		'sanitize_callback' => 'esc_url_raw'
	)
);

$wp_customize->add_control(
	new WP_Customize_Image_Control(
		$wp_customize, 'background_2xbg_upload', array(
			'label' => __( 'Current @2x Background', 'text-domain' ),
			'section' => 'background_image',
			'settings' => 'background_2xbg_upload',
			'priority' => 20,
		)
	)
);

Just replace themeslug and text-domain (for translation) with your actual theme’s slug and text-domain. Usually, these are the same string.

Adding arguments to our theme support action

Of course, for implementing background image support, just simply drop this into functions.php:

add_theme_support( 'custom-background' );

But, we want to filter the output so that it reflects our high definition background too. So, according to the article, the code that outputs the stylesheet on the front end looks like the following (ripped straight from the article):

function _custom_background_cb() {
    $background = get_background_image();
    $color = get_background_color();
    if ( ! $background && ! $color )
        return;
 
    $style = $color ? "background-color: #$color;" : '';
 
    if ( $background ) {
        $image = " background-image: url('$background');";
 
        $repeat = get_theme_mod( 'background_repeat', 'repeat' );
        if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) )
            $repeat = 'repeat';
        $repeat = " background-repeat: $repeat;";
 
        $position = get_theme_mod( 'background_position_x', 'left' );
        if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) )
            $position = 'left';
        $position = " background-position: top $position;";
 
        $attachment = get_theme_mod( 'background_attachment', 'scroll' );
        if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) )
            $attachment = 'scroll';
        $attachment = " background-attachment: $attachment;";
 
        $style .= $image . $repeat . $position . $attachment;
    }
?>
<style type="text/css">
body.custom-background { <?php echo trim( $style ); ?> }
</style>
<?php
}

The code above is the default callback that gets defined when you add theme support for a custom background. If you look at the Custom Backgrounds codex page, you will see it listed in the defaults array:

$defaults = array(
    'default-color'          => '',
    'default-image'          => '',
    'default-repeat'         => '',
    'default-position-x'     => '',
    'default-attachment'     => '',
    'wp-head-callback'       => '_custom_background_cb',
    'admin-head-callback'    => '',
    'admin-preview-callback' => ''
);

It is within wp-head-callback that you can create your own callback or adjust the default one. We will adjust the default one. On a side note, the tuts+ article was integral to my understanding of how to filter the callback, as the codex does not show you the default callback code.

Moving on, in functions.php, adjust your code like so:

$defaults = array(
    'default-color' => '',
    'default-image'          => '',
    'default-repeat'         => '',
    'default-position-x'     => '',
    'default-attachment'     => '',
    'wp-head-callback' => 'themeslug_custombg_callback',
    'admin-head-callback'    => '',
    'admin-preview-callback' => ''
);

add_theme_support( 'custom-background', $defaults );

Implementing our filter for the front end

Given the callback code above, we our going to adjust it as shown below. The new changes are in bold:

function themeslug_custombg_callback() {
    $background = get_background_image();
    $hidef_background = esc_url( get_theme_mod( 'background_2xbg_upload' ) );
    $color = get_background_color();

    if ( ! $background && ! $color ) {
        return;
    }
 
    $style = $color ? "background-color: #$color;" : '';
 
    if ( $background ) {
        $image = " background-image: url('$background');";

        $hidef_image = " background-image: url(' $hidef_background ');";
 
        $repeat = get_theme_mod( 'background_repeat', 'repeat' );
        if ( ! in_array( $repeat, array( 'no-repeat', 'repeat-x', 'repeat-y', 'repeat' ) ) ) {
            $repeat = 'repeat';
        }
        $repeat = " background-repeat: $repeat;";
 
        $position = get_theme_mod( 'background_position_x', 'left' );
        if ( ! in_array( $position, array( 'center', 'right', 'left' ) ) ) {
            $position = 'left';
        }
        $position = " background-position: top $position;";
 
        $attachment = get_theme_mod( 'background_attachment', 'scroll' );
        if ( ! in_array( $attachment, array( 'fixed', 'scroll' ) ) ) {
            $attachment = 'scroll';
        }
        $attachment = " background-attachment: $attachment;";
 
        $style .= $image . $repeat . $position . $attachment;

        $style2x = $hidef_image . $repeat . $position . $attachment;
    } ?>
<style type="text/css">
body.custom-background { <?php echo trim( $style ); ?> }

<?php if ( $hidef_background != '' ) { // begins if
?>
@media (-webkit-min-device-pixel-ratio: 1.5),
(min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2),
(min-device-pixel-ratio: 1.5),
(min-resolution: 144dpi) {
    body.custom-background {
        <?php echo trim( $style2x ); ?>
        background-size: 50%;
    }
}
<?php } // ends if ?>
</style>
<?php
}

The code above takes our high definition image, called in from our image uploader theme mod, and assigns it to $hidef_image variable. From there, this variable is assigned to the $style2x variable, along with our concatenated $repeat, $position and $attachment variables. Then $style2x is placed in a conditional statement that checks if the theme mod is not empty. It assigns the target device’s pixel ratio and displays it in the body.custom-background style rule.

Of course, you can adjust what you consider to be high definition by adjusting the device pixel ratios.

Conclusion

Using this technique, your theme’s high definition backgrounds will be one step closer to consistence with WordPress’s and one step closer to awesome!

Would you use this idea for your theme or child theme customization? Comment below.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.