Skip to content

Instantly share code, notes, and snippets.

@apkoponen
Last active November 1, 2017 08:32
Show Gist options
  • Select an option

  • Save apkoponen/69613decf11e13454ae4 to your computer and use it in GitHub Desktop.

Select an option

Save apkoponen/69613decf11e13454ae4 to your computer and use it in GitHub Desktop.
Output a style tag with responsive background image sizes (for WordPress 4.4 and up).
/**
* Output a style tag with responsive background image sizes.
*
* Example:
*
* the_attachment_image_responsive_bg_style(132, "#section-top", 40)
*
* For attachment ID 132, for an element with id="section-top" and a page
* with 20px padding on both sides of the element.
*
* @param int $attachment_id Attachment ID
* @param string $selector CSS-selector
* @param int $page_padding Horizontal padding around the element for calculating min-width
*/
function the_attachment_image_responsive_bg_style($attachment_id, $selector, $page_padding = 0)
{
$srcset = wp_get_attachment_image_srcset($attachment_id);
$sets = explode(', ', $srcset);
if (is_array($sets)) {
echo '<style>';
$smallest_image_url = '';
$smallest_width = 9999;
foreach ($sets as $set) {
list($url, $width) = explode(' ', $set);
if ($smallest_width > $width) {
$smallest_image_url = $url;
}
$width = str_replace('w', '', $width) + $page_padding;
?>
@media (min-width: <?php echo $width; ?>px) {
<?php echo $selector; ?> {
background-image: url(<?php echo $url; ?>);
}
}
<?php
}
echo $selector; ?> {
background-image: url(<?php echo $smallest_image_url; ?>);
}
<?php
echo '</style>';
}
}
@tomkeysers
Copy link

Way cool. Nice fix :) was looking for this.

@tomkeysers
Copy link

After thoroughly testing it out, it seemed that the last selector on line 41 was always overriding the rest.
After commenting that out, I found that the selector's background image was always one size too small.
E.g. min-width: 300px got image300x100, up until a width of 768px ... but that's actually not correct. Up until 768px you should get the image768px100. So I rewrote your function a little bit:

function the_attachment_image_responsive_bg_style($attachment_id, $selector, $page_padding = 0)
{
    $srcset = wp_get_attachment_image_srcset($attachment_id);
    $sets   = explode(', ', $srcset);

    if (is_array($sets)) {
        echo '<style>';

        $smallest_image_url = '';
        $smallest_width = 9999;
        $min_width = 0;

        foreach ($sets as $set) {
            list($url, $width) = explode(' ', $set);
            if ($smallest_width > $width) {
                $smallest_image_url = $url;
            }
            $width = str_replace('w', '', $width) + $page_padding;
            ?>
            @media (min-width: <?php echo $min_width ?>px) and (max-width: <?php echo $width; ?>px) {
                <?php echo $selector; ?> {
                    background-image: url(<?php echo $url; ?>);
                }
            }
            <?php

            $min_width = $width+1;
        }

        echo '</style>';
    }
}

Like this it writes the media queries with min- and max-width.
E.g.:

@media (min-width: 0px) and (max-width: 300px) {
         #front-hero {
                    background-image: url(//localhost:3000/wp-content/uploads/2015/12/test-bg-300x94.jpg);
         }
}
@media (min-width: 301px) and (max-width: 768px) {
          #front-hero {
                    background-image: url(//localhost:3000/wp-content/uploads/2015/12/test-bg-768x240.jpg);
          }
}

@sinashamsizadeh
Copy link

Good job

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