3

I am setting the featured image as a background for the top part of the page. The images are quite large and I'd like to be able to set smaller image sizes for smaller screen sizes. Since the images are added inline, I don't think I can use the external styles.css file to set different images.

Here's an example of what I have:

<?php 
$bannerImg = '';
if(has_post_thumbnail()) {
    $bannerImg = get_the_post_thumbnail_url();
}
?>

<section class="page-banner" style="background-image: url(<?php echo $bannerImg; ?>);">
    <h1 class="banner-title"><?php the_title(); ?></h1>
</section>

I'd like to do something like srcset but I couldn't find an equivalent for background images.

  • This is most likely not really specific to WordPress and therefore off-topic to this site. Have a look at the generel Stack Overflow site for topics related to your question. – flomei Mar 29 '17 at 23:18
  • 1
    I'm thinking this might be on-topic. Ideally one would just use image-set (background-image equivalent to srcset) but it's not widely implemented at this point. I think there are work-arounds which would leverage native WordPress functionality. @flomei - most of the links that Google search bring up detail solutions which just scale the image up or down, which is not sufficient in this instance. @erin_k what's your reasoning for choosing background-image over an <img> as a child of <section>? – bosco Mar 30 '17 at 1:25
  • 1
    Thanks @flomei. I wasn't sure where to post this but since I'm using WordPress API in my code sample I thought if I posted it in the general Stack Overflow that they'd tell me to post it here. – erin_k Mar 30 '17 at 17:51
  • @bosco I did see image-set but after doing further research saw that it is not supported in FF or IE. Maybe this is not too much of an issue since most mobile devices use Chrome or Safari anyway but I thought I'd pose the question to the community for alternate solutions. To your question about using <img>, yes I've considered that as well. I set it as a background-image because I have text and other elements overlayed on top so it felt like the proper use semantically. If there isn't a good solution to this, I may just switch them out to be images. – erin_k Mar 30 '17 at 17:53
  • No problem, I probably did not read your question right, keep it to WPSE for now, I think. ;-) – flomei Mar 31 '17 at 7:39
0

If you use Adaptive Images plugin for WordPress, you would just make one inline css for all viewport widths using the biggest image and then it does all the work on the server. You do nothing to your markup but in the Adaptive Images plugin settings you enter your breakpoints, so it will serve small images to small devices and so forth.

If you use Adaptive Images it would be:

/**  
 *
 * Background Image from Post Image using Adaptive Images Plugin for WordPress
 * @since  1.0.0
 * Credits: TwentyFifteen WordPress theme adjacent pagination
 *
 */
function the_other_idea_good_heavens_change_this_function_name() {

    global $post;

    if ( ! has_post_thumbnail( $post->ID ) ) return; //exit if there is no featured image

    $theme_handle = 'visionary'; //the theme handle used for the main style.css file

    //image
    $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'super-huge-image' );

    //css
    $css = '.banner-image { background-image: url(' . esc_url( $image[0] ) . '); } ';

    //minify            
    $css = str_replace( array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $css );

    //add it
    wp_add_inline_style( $theme_handle, $css );

}
add_action( 'wp_enqueue_scripts', 'the_other_idea_good_heavens_change_this_function_name', 99 );

This is what I do (before I started using Adapative Images ).

add_image_size();

I use three sizes small, medium, large in this example and then I regenerate my thumbnails.

/**  
 *
 * Background Image from Post Image
 * @since  1.0.0
 * Credits: TwentyFifteen WordPress theme adjacent pagination
 *
 */
function yourprefix_responsive_mobile_first_background_images() {

    global $post;

    if ( ! has_post_thumbnail( $post->ID ) ) return; //exit if there is no featured image


    $theme_handle = 'visionary';     //the theme handle used for the main style.css file
    $property     = '.banner-image'; //the property
    $css          = '';

    //small image
    $small_img   = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'my-small-image-size' );
    $small_style = '
            ' . $property . ' { background-image: url(' . esc_url( $small_img[0] ) . '); }
            ';
    $css .= $small_style;


    //medium image
    $medium_img   = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'my-medium-image-size' );
    $medium_style = '
            ' . $property . ' {  background-image: url(' . esc_url( $medium_img[0] ) . '); }
            ';
    $css .= '@media (min-width: 1000px) { '. $medium_style . ' }';


    //large image
    $large_img   = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'my-large-image-size' );
    $large_style = '
            ' . $property . ' {  background-image: url(' . esc_url( $large_img[0] ) . '); }
            ';
    $css .= '@media (min-width: 1700px) { '. $large_style . ' }';

    //minify            
    $css = str_replace( array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $css );

    //add it
    wp_add_inline_style( $theme_handle, $css );

}
add_action( 'wp_enqueue_scripts', 'yourprefix_responsive_mobile_first_background_images', 99 );
  • Thank you @Christina. I should have specified I was looking for a non-plugin solution but it looks like Adaptive Images would work as an option. A question on the second part of your answer. It looks like that code would output style tags in the head part of the template, with the media queries specified, is that correct? Just want to make sure I'm understanding what I'm looking at. Thanks so much. – erin_k Mar 31 '17 at 17:34
  • It is CSS that outputs just like a customizer function would do when you add something to a field, but we don't have a front end field, we are getting the featured image for that page and putting that as a background in CSS and not inline on the tag itself, much better for speed as mobile first loads only the background specified for the viewport width range. – Christina Mar 31 '17 at 17:54
  • This is basic CSS for mobile first, it just looks more techy here. I would use a fallback image in your CSS file that accounts for auto generated pages that don't have a featured image like archives, search, tags, etc., you can you can use css for that if you filter the body class to put the slug on there. Might want to google around, this is a common design idea so there are plenty of ideas. – Christina Mar 31 '17 at 17:54
  • 1
    I tried this out and it works great! Thanks @Christina! I ended up using your second suggestion (not Adaptive Images). I also set up a backup image in cases where no featured image is provided. In my particular case, a mix of changing the background images to <img> instead and also using this code where a background-image was needed ended up being my approach. – erin_k Apr 3 '17 at 19:11
  • It was good timing since I just did something similar on a site I'm working on. – Christina Apr 3 '17 at 21:10
-1

You can simply  use CSS media query for different device one example 

@media only screen and (max-width: 320px) {
    /* styles for narrow screens */
   .page-banner{
     background-size:100% auto;
     background-repeat:no-repeat;
     background-position:center;
     display: block;
     width: 100%;
     height: 500px;
    }

}

You can use different page different class id 
page-id-34 logged-in wpb-js-composer js-comp-ver-4.12 vc_responsive">
  • I have the background images set inline on the page not in an external stylesheet so I'm not sure how this solution would work. I need different images served up for different browser sizes. Thanks – erin_k Mar 30 '17 at 17:57
  • @erin_k Media queries might actually be plausible, if you set background-image-url in them and don't inline the rule on the element itself (or remove the in-lined rule after page-load using JS to prevent the FOUC). You'd need to dynamically create the CSS in a <style> element containing media queries appropriately constructed based on WP's responsive image functions and print it to the markup - either in the appropriate theme template itself, or possibly using a conditional wp_head hook or some such. – bosco Mar 30 '17 at 21:46
  • It should definitely work, but still maybe a little "messy". I'm not fond of using PHP to generate CSS rules, for whatever reason. I'm starting to think sticking with <img> to leverage WP's native functionality might be the best solution until image-set catches up. – bosco Mar 30 '17 at 21:58
  • Thanks @bosco. You presented two possible solutions/workarounds and I agree, I think switching them to images might be my best bet. I will accept your answer if you create one. – erin_k Mar 30 '17 at 23:57

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.