Skip to content

Instantly share code, notes, and snippets.

@joshuadavidnelson
Last active January 22, 2024 12:42
Show Gist options
  • Select an option

  • Save joshuadavidnelson/eb4650aa1ee8da9c7d731960e9402e21 to your computer and use it in GitHub Desktop.

Select an option

Save joshuadavidnelson/eb4650aa1ee8da9c7d731960e9402e21 to your computer and use it in GitHub Desktop.
Using WordPress responsive images for css background-image property, in-line styling
<style>
.header {
background-image: url(http://local.dev/wp-content/uploads/2016/04/image-300x151.png)
}
@media only screen and (min-width: 300px) {.header {
background-image: url(http://local.dev/wp-content/uploads/2016/04/image-768x386.png)
}}
@media only screen and (min-width: 768px) {.header {
background-image: url(http://local.dev/wp-content/uploads/2016/04/image-1024x515.png)
}}
@media only screen and (min-width: 1024px) {.header {
background-image: url(http://local.dev/wp-content/uploads/2016/04/image.png)
}}
</style>
<?php
/**
* Generate some inline styles for use with the background-image and responsive images in WordPress.
*
* Uses wp_get_attachment_image_srcset to gather the image urls and device sizes.
* A mobile-friendly application of the background-image property.
* In this example, it's setup for a full-width image
*
* @author Joshua David Nelson, josh@joshuadnelson.com
*/
$image_id = get_post_thumbnail_id(); // set or grab your image id
$img_srcset = wp_get_attachment_image_srcset( $image_id, 'full' );
$sizes = explode( ", ", $img_srcset );
$css = '';
$prev_size = '';
foreach( $sizes as $size ) {
// Split up the size string, into an array with [0]=>img_url, [1]=>size
$split = explode( " ", $size );
if( !isset( $split[0], $split[1] ) )
continue;
$background_css = '.header {
background-image: url(' . esc_url( $split[0] ) . ')
}';
// Grab the previous image size as the min-width and/or add the background css to the main css string
if( !empty( $prev_size ) ) {
$css .= '@media only screen and (min-width: ' . $prev_size . ') {';
$css .= $background_css;
$css .= "}\n";
} else {
$css .= $background_css;
}
// Set the current image size as the "previous image" size, for use with media queries
$prev_size = str_replace( "w", "px", $split[1] );
}
// The final css, wrapped in a <style> tag
$css = !empty( $css ) ? '<style>' . $css . '</style>' : '';
@rsynnot

rsynnot commented Jun 12, 2017

Copy link
Copy Markdown

This is awesome.
But where do the media query breakpoints come from?
Mine are different to yours in your output there...

.hero-photo {
		background-image: url(...)
}
@media only screen and (min-width: 5846px) {.hero-photo {
		background-image: url(...)
}}
@media only screen and (min-width: 300px) {.hero-photo {
		background-image: url(...)
}}
@media only screen and (min-width: 768px) {.hero-photo {
		background-image: url(...)
}}
@media only screen and (min-width: 750px) {.hero-photo {
		background-image: url(...)
}}

I added in an IF statement to omit giant 'full' size images from the initial CSS rule:

if( !empty( $prev_size ) ) {
	//so a size now exists
	if ($prev_size <= 1280 ){
		$css .= '@media only screen and (min-width: ' . $prev_size . ') {';
		$css .= $background_css;
		$css .= "}\n";
	}
} else {
	$css .= $background_css;
}

And now that first huge image does not appear 😄

@ronca85

ronca85 commented Jul 21, 2017

Copy link
Copy Markdown

i have a project with an owl carousel 2 slider on the front-page with background images showing up inside. how do i use this code to makethe images responsive?

@mariannag7282

Copy link
Copy Markdown

Thank you for this. Where would I place your code to generate the responsive background-image?

@MaikelGG

MaikelGG commented Jul 2, 2020

Copy link
Copy Markdown

Thanks for this snippet.
Perhaps something changed in the Wordpress function but I needed to add sort($sizes); to get the order right, otherwise it is all mixed up. Maybe somebody will run into the same issue....

@ggeiger

ggeiger commented Sep 22, 2020

Copy link
Copy Markdown

Thanks for the original code! It inspired me to complete a different version. I ended up creating a function (added to functions.php):

function getSrcSet($id) {

  $img_srcset   = wp_get_attachment_image_srcset($id, 'full');
  $srcset_array = explode(", ", $img_srcset);
  $images  = array();
  $x = 0;

  foreach ($srcset_array as $set) :

    $split = explode(" ",$set );

    if (!isset($split[0], $split[1])) continue;

    $images[$x]['src'] = $split[0];
    $images[$x]['width'] = str_replace('w', '', $split[1]);

    $x++;

  endforeach;
  
  // sort the array, ordered by width
  usort($images, function($a, $b) {
    return $a['width'] <=> $b['width'];
  });

  return $images;
}

Then in my template file I'm calling the function and looping through the results:

$css = '';
$image_id = get_post_thumbnail_id();
$srcset = getSrcSet($image_id);

foreach ($srcset as $set) :

  // skip big ones
  if ($set['width'] > 1600) continue;

  $css .= '@media only screen and (min-width: ' . $set['width'] . 'px) {
    .slide { background-image: url(' . $set['src'] . '); } }';

endforeach; ?>
  	
<div class="slide"></div>
 
<?php $css = !empty($css) ? '<style>' . $css . '</style>' : ''; echo $css; ?>

@ensignrolaren

Copy link
Copy Markdown

@ggeiger Thanks for your rewritten code– it does the job nicely. The addition of the custom usort() function solves the problem I was having with the original where the wp_get_attachment_image_srcset() function called the sizes out of order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment