Search code examples
htmlimagewebpresponsive-imagespagespeed-insights

HTML picture element downloading wrong image on mobile


I'm running a page through Google's Page Speed Analyzer and for mobile, it's telling me I should download the proper size images. I know the viewport size, but I don't know the width of the slot because we are using a responsive layout. I've looked at the documentation and a bunch of examples and none of them are using what I think should be the correct image.

The Network tab of developer tools is showing we are downloading about.webp for mobile and not either of the smaller images (200px or 400px). Even when changing the device in Chrome to a smaller viewport width, it still downloads about.webp.

What is the correct HTML for a picture element to get Page Speed Analyzer to use the appropriate image?

Below is my picture element. Thanks!

<div class="row"><div class="col-md-3">
    <picture>
        <source type="image/webp" 
            sizes="(max-width: 200px) 200px,
              (max-width: 400px) 400px,
              (max-width: 1500px) 1500px" 
            srcset="//cdn.storyboardthat.com/site-images/articles/education/about-sbt-w200.webp 200w,
//cdn.storyboardthat.com/site-images/articles/education/about-sbt-w400.webp 400w, 
//cdn.storyboardthat.com/site-images/articles/education/about-sbt.webp 1500w">
        <source type="image/png" 
            sizes="(max-width: 200px) 200px, 
              (max-width: 400px) 400px, 
              (max-width: 1500px) 1500px" 
            srcset="//cdn.storyboardthat.com/site-images/articles/education/about-sbt-w200.png 200w, 
//cdn.storyboardthat.com/site-images/articles/education/about-sbt-w400.png 400w, 
//cdn.storyboardthat.com/site-images/articles/education/about-sbt.png 1500w">
            <img src="//cdn.storyboardthat.com/site-images/articles/education/about-sbt.png" 
              alt="Storyboard That" 
              title="Storyboard That" 
              class="lazyload " 
              style="max-width:100%;height:auto;" 
              width="1500" height="400" loading="lazy"> 
    </picture>
</div>


Solution

  • You have forgotten about Device Pixel Ratio (DPR).

    You see the <picture> element basically says to browsers "here are a few options to choose from, I have indicated my preference but it is up to you to decide which image you think is best".

    As you haven't specified a DPR preference the browser is using the following logic:

    "Ok so I have 3 images to choose from, what is my current DPR? Oh I have DPR set to 3.

    How big is the image at this screen width (320px)? Full screen width so I need a 320px image.

    Ok so it is 320px * 3 DPR to ensure I have the highest quality image that matches my current display resolution.

    So I need a 960px image minimum. My options are 200, 400 or 1500, I better choose the 1500 image and down sample it."

    So how do I control pixel density decisions?

    You can specify pixel density with 1x, 2x, 4x etc. For example:

    <img src="default.webp"
    srcset="hiddef.webp 2x, heighestdef.webp 4x"
    alt="Image description">
    

    However with how you have currently structured your picture element it won't quite work as you can't combine image 200w with image 2x to do image 200w 2x.

    If you want to keep the same image at all DPIs then you would specify that image 3 times.

    <img src="default.webp"
    srcset="default.webp 2x, default.webp 4x"
    alt="Image description">
    

    Otherwise if you want the browser to change the image automatically based on DPR just leave your <picture> element as it is.