jmng
jmng

Reputation: 2568

srcset - Responsive image loading wrong file

My goal is to serve different versions (resolutions/sizes) of the same image, which should occupy 100% of the width of the viewport, so I can serve a 800px version to mobile devices (or, generally, devices with smaller displays or slower connections), 1366px and above to larger desktop displays.

The problem is that I'm testing it with the Chromium device emulator and some small screen devices load the 1366px version instead of the 800px: the iPhone 6/7/8 (375px width) loads the 800px image, but the iPad (768px), Nexus 5 (360px) and iPhoneX (375px) all load the 1366px instead of loading the 800px.

I'm not very confident of having understood the sizes directive properly, here's my code, the default src references the 2880px version just to help testing:

<img class="img-fluid" 
    srcset="img/dreamstime_800w_109635242.jpg 800w,
         img/dreamstime_1366w_109635242.jpg 1366w,
         img/dreamstime_2880w_109635242.jpg 2880w"
    sizes="(max-width: 800px) 100vw,
        (max-width: 1366px) 100vw,                      
        2880px 100vw"
    src="img/dreamstime_2880w_109635242.jpg"/>

Upvotes: 5

Views: 4973

Answers (6)

HandiworkNYC.com
HandiworkNYC.com

Reputation: 11124

simple answer:

sizes="(max-width: 999px) 50vw, 100vw"

Upvotes: -2

Max
Max

Reputation: 334

I noticed that when the chrome devTools is open with the responsive mode enabled, my device pixel ratio changed from 1 to 2. As a result, even with cache disabled in network tab, it seemed to me the browser was loading a larger file than necessary, but it's because the pixel ratio changed when:

  1. the devTools was open
  2. responsive mode was enabled

You can double check with a simple javascript alert the pixel ratio at any given time:

<script>alert(window.devicePixelRatio)</script>

It's likely you have responsive mode enabled if you try to load your page at multiple width for testing, but it's also what might change the pixel density. Thus, it might just work as intended like it was for me.

Upvotes: 0

Duns
Duns

Reputation: 438

Testing my web pages with the Chrome emulator, I sometimes found (like you did) that an image larger than necessary was apparently being loaded, particularly on small mobile devices. I finally realized that this was not an error on my part but Chrome pulling a larger image from cache if it happened to have one there. Clicking the checkbox in the emulator to disable the cache while testing, the problem went away and the sizes I expected to see loaded were in fact loaded.

Upvotes: 1

for future readers - i had a hard time understanding why srcset was totally ignoring my attempts. After a couple hours of frustration and anger i came thru the most obvious answer in the world - i'm working on a Retina Macbook Pro, and i wasn't triggering pixel density.

I changed it to

<img class="<?= $image_class;?>" data-caption="<?php echo $image['alt']; ?>"
data-src="<?php echo $image['sizes']['medium']; ?>"
data-srcset="<?php echo $image['sizes']['medium']; ?> 600w 2x, 
<?php echo $image['sizes']['large']; ?> 1280w 2x"
sizes="(min-width: 150px) 600px, 100vw"
width="150" height="150"
alt="<?php echo $image['alt']; ?>">

and everything worked - at least i could figure out something was happening. Phew. Merry Xmas everybody!

Upvotes: 1

Nicolas Hoizey
Nicolas Hoizey

Reputation: 2031

Your sizes attribute tells the browser the image is always shown full viewport width, so you could simply replace it with sizes="100vw".

So the browser takes current viewport width, multiply it with screen density, and it gives it the width of the required image. It then takes the closest image from the list in the srcset.

You can't use it to ”serve a 800px version to mobile devices”, because most mobile devices nowadays have bigger density than desktop devices and you can't prevent it with <img srcset… sizes…>.

If you really want to ignore screen density (for what reason?) and:

  • serve smallest images to small devices,
  • serve medium image to medium devices
  • serve large image to large devices
  • keep largest image as the fallback

Then you have to use <picture> with media queries like that:

html <picture> <source media="(max-width: 800px)" srcset="img/dreamstime_800w_109635242.jpg 800w"> <source media="(max-width: 1366px)" srcset="img/dreamstime_1366w_109635242.jpg 1366w"> <img src="img/dreamstime_2880w_109635242.jpg"> </picture>

Upvotes: 5

Heiruspecs
Heiruspecs

Reputation: 129

This has to do with retina displays (and their DPI, I think).

From what I've heard, retina displays will pick the first image that is either twice or three times the width of their display, depending on their respective retina display (2x, 3x etc).

Another simple solution would be clearing your browser cache. If your biggest and baddest image has already been cached, Chrome (for example) will always load that image instead.

Upvotes: 4

Related Questions