Srcset DPR source switching

Found something interesting when I was playing around with srcset and retina sizing 1x, 2x etc.

When having an img element with srcset with 1x & 2x images, they behave mostly as you’d expect. If your DPR is 1, then you get the 1x image. If it’s 2, you get 2x.

However, as I was playing around with various DPRs to see how it worked out the logic of whether to serve the 1x or 2x in between those DPRs. I found something interesting. I’m not sure if this is a bug, or how it’s intended to work and I’m just unaware of the logic going on.

So, if I set the DPR to 1.41. Then I’m served the 1x image. If I set it to 1.42. Then I’m served the 2x image.

I’m not sure if it’s relevant, but the image in question was 182 x 142px wide, and the 2x exactly double that.

Any thoughts? @yoavweiss in particular?


Edit: This is in Chrome 43

If the device pixel ratio is between two available resolutions, you want to use the larger image and downsample its details - that’s the whole point of providing a larger image, to not lose detail the device is capable of displaying (but avoid transmitting detail the device is not capable of displaying). Without looking, I would expect this is explicitly codified as part of the <picture> spec.

Absolutely, I’m just curious as to why it’s switching sources at 1.41 & 1.42. Just wondering what the logic is there and if that’s correct.

Oh wow, I missed that, I thought you were saying it switched above 1x. Yeah, that’s weird.

Link to the <picture> spec.

1 Like

It sounds like it’s switching around the square root of 2 - can you confirm if this also happens between 1.413 and 1.415?

Bang on sir! 1.413 = 1x. 1.415 = 2x.

Cheers :slight_smile:

Chrome uses a geometric mean based algorithm to detect which of the provided resources is “closer” to the DPR. In you case, the geo-mean of 1 and 2 is the square root of 2, as you guessed :smile:

The resource selection is not part of the spec (the spec defines this as UA specific).

We’ve had complaints in the past that caused this algorithm to change, from “never upscale” to “geo-mean” and now to “geo mean if the screen’s DPR is higher than 1”. It’s trade-off between quality and bandwidth, and I think we’re still looking for the sweet-spot.

It would be nice if there were a non-normative note in the spec that describes the implementors/RICG’s progress in this vein, so devs looking at the spec know what to expect (though it would also be nice if content authors didn’t have to go as far out as to the specs to find this information).

Might be useful to introduce operators… e.g.

<img srcset="/graphic.jpg <= 1x, /graphic@2x.jpg > 1x && <= 2x" />

I know that looks hideous, but something along those lines might be interesting. It would give you finite control over what resources are displayed, rather than leaving it up to logic, which may or may not be defined and the same across vendors.

Or something less insane, maybe.

<img srcset="/graphic.jpg *-1x, /graphic@2x 1.01-2x">

Again, not pretty, but along those lines

Or maybe make the upscaling behavior exposed and configurable via a CSS property. (Or a <meta> tag or JS API, but I think the CSS property would be the best solution here.)

x descriptors are not shorthand media queries. They do not describe the device-pixel-ratio that the resource is intended for. They do describe the resource’s size relative to it’s img’s layout size, and the browser is given explicit permission to choose whichever resource it wants, given that information.

This is good, because the browser knows a lot more about its context than you do. Describing, rather than proscribing, resources lets the browser make good decisions in contexts that authors haven’t or couldn’t anticipate; srcset, as specced, is future friendly.

If you do want explicit control, use media queries with picture & media:

  <source srcset="/graphic@3x" media="(min-device-pixel-ratio: 2.01)" />
  <source srcset="/graphic@2x" media="(min-device-pixel-ratio: 1.01) and (max-device-pixel-ratio: 2)"
  <img src="/graphic.jpg" alt />

But I would think long and hard about using markup like this when all you want to do is send crisp images to HiDPI screens. Browsers have a wealth of info about user preferences, connection speed… what resources may already be in the cache… don’t rob them of their ability to use it!