3

I work on a theme that displays 3 columns with images, so the size for thumbnails on large displays will be 360x240px.

When resized, on some mobile devices, like iPhone, there will be just 1 column with images, which may result that the featured image will be larger than 360px in width.

Now, in order to maintain a good PageSpeed score, I don't want to load a larger image size on desktop computers and scale it via CSS, but on mobile devices I need the Featured Image to be larger, like 640x426px.

The problem in using the same image size on mobile devices is that it may not be large enough to fill 1 column, and would leave some empty space next to it.

I've registered 2 new image sizes, but it seems that the the_post_thumbnail() function always picks the wrong one.

add_image_size( 'loop', 360, 240, true );
add_image_size( 'loop-mobile', 640, 426, true );

I've tried different methods, and none of them is close to what I need:

  1. the_post_thumbnail();

    In this case the image is too small on mobile devices

  2. the_post_thumbnail('loop-mobile');

    In this case it will always load the larger version 640x426px, which affects the PageSpeed score

  3. the_post_thumbnail(array(640,426));

    Same problem with PageSpeed score.

Thanks for help!

3 column on desktop

1 column on mobile

1
  • You regenerate thumbnails? Use this plugin
    – nicogaldo
    Mar 29, 2016 at 14:04

2 Answers 2

2

The answer is to use WP's responsive images, customising the sizes attribute to suit your use case.

Reading between the lines, I'm assuming here that you are using a responsive design approach to show the different layouts at different widths.

The easiest way is to start by making yourself a replacement template tag function for the_post_thumbnail:

function wpse_221989_the_post_thumbnail( $size, $attr ) {
    the_post_thumbnail( $size, $attr );
}

Where you call the_post_thumbnail in your templates, call wpse_221989_the_post_thumbnail instead. Why do we do it like this? WP doesn't give you any context on the filter hooks to modify srcset and sizes attributes for responsive images, so we are making our own context with the wpse_221989_the_post_thumbnail wrapper function.

So far, nothing clever, but now we can build upon this function to:

1 - draw on a set of image sizes

2 - ask the browser to choose a suitable image depending upon your responsive breakpoint for this particular use case

1 - In your instance, where your image versions are all the same aspect ratio, WP handles things for us. Using a built-in image call like the_post_thumbnail will build a srcset attribute from every image size you have with the same aspect ratio as the image specified in the $size parameter. You can use add_image_size to create additional versions large enough for high density displays too. WP's match on aspect ratio allows for small rounding errors, so both the sizes in your question should be matched OK.

2 - To get the browser to choose the right image size for the space, you will need a custom sizes attribute. WP's default sizes attribute assumes that you want an image to be full browser width, but no wider than the image's natural width. In your design, narrower screens need the larger image and then above a certain breakpoint you want to choose the smaller image width.

So, assuming from your image sizes that your breakpoint is at 640px, we'd want a sizes attribute a bit like this: (min-width: 640px) 33.333vw, 100vw

What this says to the browser is for windows of 640px width and over, choose the image from the srcset list that best matches a third of the window width. For other window widths (< 640px) choose an image from the list that best fits the full window width.

To put that into code we make a new function to return the attribute and build it into our wrapper function:

function wpse_221989_sizes() {

    return "(min-width: 640px) 33.333vw, 100vw";

}

function wpse_221989_the_post_thumbnail( $size, $attr ) {

    add_filter( 'wp_calculate_image_sizes', 'wpse_221989_sizes', 10 , 2 );
    the_post_thumbnail( $size, $attr );
    remove_filter( 'wp_calculate_image_sizes', 'wpse_221989_sizes', 10 );

}

Now when your theme template calls wpse_221989_the_post_thumbnail our custom sizes attribute will be substituted for the default. By hooking into the filter before calling the_post_thumbnail and unhooking immediately after we make our custom template tag function sensitive to the context of your question without upsetting any sizes attributes generated on images in other parts of your theme.

You can build upon this by putting in conditional checks on $size to choose different rules for the various image versions you've created for your theme to use.

If Google Pagespeed is important to you then test to see that it is obeying your srcset and sizes attributes. If not, then use add_image_size to make a size that just fits the Pagespeed window and use that size in your calls to wpse_221989_the_post_thumbnail so that it is put into the src attribute. On my sites I use a 1024px image as the default which seems to keep both desktop and mobile Pagespeed analyses happy.

1

Your problem comes from not doing responsive design. Responsive design should leave everything to be decided at the client side, attempts to serve something that will match all screen sizes at the server code will usually fail or prevent you from using caching.

The ideal solution is the srcset attribute W3C HTML 5+ docs, unfortionatly its default implementation in wordpress sucks and you will need to use relevant API to have it match the images as you want them to be, where you want them to be.

Note: srcset is just a recommendation to the browser it does not have to follow, if you do not want to leave it to the mercy of browsers, you will need to find a JS library that does similar things.

2
  • Mark, please mind your language. Also when you are already using words to describe your opinion on a specific part of the API and rate it good or bad, then please add at least a reason (read: example code to visualize and support your statement) why you think it's good or bad.
    – kaiser
    Mar 29, 2016 at 13:37
  • @kaiser, noted. Mar 29, 2016 at 14:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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