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.
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.
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
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.
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.
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!