htmlimageresponsive-imagessrcsetpixel-density

responsive images with srcset, sizes, media-queries - Prevent loading huge images for higher pixel density


I used picture element for responsive images in different sizes per viewport a long time. it worked fine, but now I am forced to switch over to responsive <img> with srcset and sizes and I try to rewrite my picture element to the IMG-style.

After long searching I found good documentations at:

https://www.dofactory.com/html/img/sizes and more details at: https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images

The code with picture was like this:

<picture>
    <source media="(max-width: 740px)" src="740.jpg" type="image/jpeg">
    <source media="(max-width: 980px)" src="1280.jpg" type="image/jpeg">
    <source media="(max-width: 1280px)" src="1600.jpg" type="image/jpeg">
    <source media="(max-width: 1480px)" src="1920.jpg" type="image/jpeg">
    <img src="740.jpg" title="..." alt="..." />
</picture>  

I re-wrote this to an responsive img like this:

<img src="740.jpg" title="..." alt="..." 
    srcset="
       740.jpg 740w,
       1280.jpg 1280w,
       1600.jpg 1600w,
       1920.jpg 1920w" 
    sizes="
       (max-width: 740px) 740px,
       (max-width: 980px) 1280px,
       (max-width: 1280px) 1600px,
       (max-width: 1480px) 1920px"
/>

This seems work wonderful on the first tests in browser. But then I noticed that on mobile devices it loads too big images.

The reason was the different pixel density of some mobile devices like explained at a-complete-guide-for-responsive-images

You can simulate this with dev-tools of firefox too: Firefox dev-tools

I tried to fix this with changing my code to

<img src="1920.jpg" title="..." alt="..." 
    srcset="
       740.jpg 740w 1x,
       1280.jpg 1280w 1x,
       1600.jpg 1600w 1x,
       1920.jpg 1920w 1x" 
    sizes="
       (max-width: 740px) 740px,
       (max-width: 980px) 1280px,
       (max-width: 1280px) 1600px,
       (max-width: 1480px) 1920px"
/>

Does not work... (it always loads the smallest image for all viewpoints)

I tried the a solution without media queries in sizes from Handling responsive images with img srcset

Not working like I need it ...

So the big question is, how can selectores for width and density be combined.

In my example it should load:

And I DON`T want that it loads bigger images for devices with a bigger pixel density.

I know there are lots of similar questions in Stackoverflow, and I am searching for weeks for a working soluting, but nothing seems to work like expected, so I hope somebody can offer a solution

UPDATE: I found out, that there is an gitlab issue where this problem is discussed.

2

(see Responsive images causes performance issues)

But for now it seems that there is no final solution for the problem.

Would be very glad if anybody could offer new ideas.


Solution

  • I found 2 possible solutions:

    Both use the min-resolution media-query to define separate sizes per pixel density. I use a more simple example than in the question to explain it:

    Idea 1

    <img src="500.jpg" title="..." alt="..." 
        srcset="
           500.jpg 500w,
           1000.jpg 1000w"
        sizes="
           (min-resolution: 3dppx) 33vw,
           (min-resolution: 2dppx) 50vw,
           (min-resolution: 1dppx) 100vw"
    />
    

    I used the 100vh examples, and "reverted" that the browser takes images that are current_with * pixel-density.

    This solution works for full-screen images, but you can use custom viewports.

    Idea 2

    <img src="500.jpg" title="..." alt="..." 
        srcset="
           500.jpg 500w,
           1000.jpg 1000w"
        sizes="
           (min-resolution: 3dppx) and (max-width: 600px) 1500px,
           (min-resolution: 3dppx) and (max-width: 1200px) 2000px,
    
           (min-resolution: 2dppx) and (max-width: 600px) 1000px,
           (min-resolution: 2dppx) and (max-width: 1200px) 2000px,
    
           (min-resolution: 1dppx) and (max-width: 600px) 500px,
           (min-resolution: 1dppx) and (max-width: 1200px) 1000px"
    />
    

    I created similar media-queries based on screen-width, but added sizes that "reverted" that the browser takes images that are current_with * pixel-density.

    This solution for all images, even if they are not full size. Here you can use custom viewports, but it is relativ much code.

    The basic idea behind both:

    In summery that means:

    if you like to revert the effect that browser takes bigger images for mobil-device with big pixel-denstity you must calculate new values for your sizes for each pixel-density.

    For both solutions you should define the display sizes via css too.

    E.g. this example simple php-code shows that:

    <?php
      $viewport = [
        // Viewport => Image-Size
        600  => 500,
        1200 => 1000
      ];
    
      // walk over all pixel-densities
      for($i=3; $i>0; $i--) {
        foreach($viewport as $vp => $w) 
          echo "(min-resolution: {$i}dppx) and (max-width: {$vp}px) "
                .floor($w/$i) . "px,\n";
      }
    ?>