New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 788105 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Nov 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 2
Type: Bug



Sign in to add a comment

Responsive images: incorrect source is chosen from srcset on high-DPR devices

Reported by oliverj...@gmail.com, Nov 23 2017

Issue description

UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36

Steps to reproduce the problem:
1. Open a new tab
2. Open dev tools' Device Mode
3. Emulate a width of 300 and DPR 2
4. Go to http://output.jsbin.com/cahosiz/11/quiet

What is the expected behavior?
The sizes attribute declares 100vw, so the parsed size in this case is 600px (viewport width * DPR = 300px * 2). As far as I understand, the browser should round up the parsed size to the nearest matching width descriptor in srcset.

Therefore I would expect it to match the 1000w srcset entry.

What went wrong?
The browser matches the 500w srcset entry.

Did this work before? N/A 

Does this work in other browsers? N/A

Chrome version: 62.0.3202.94  Channel: stable
OS Version: OS X 10.13.1
Flash Version:
 

Comment 1 by f...@opera.com, Nov 23 2017

"100vw" would resolve to "300px" (the viewport width in CSS pixels - not device pixels.)
Yes, that's right. But, as far as I understand, to find a matching source from srcset the browser should multiply the parsed size with the DPR, i.e. parsed size * DPR = 100vw * 2 = 300px * 2 = 600px.

Comment 3 by f...@opera.com, Nov 23 2017

In this case, the spec calls for computing a "normalized" source density, which in this case would mean 500 / 300 and 1000 / 300 (so 1.66... and 3.33...) and then select a source based on that. The actual selection logic is implementation-specific. In this particular case, with Blink's selection logic, the value used for selection will be sqrt(1.66... * 3.33...) ~= 2.3 and since that is less than the DPR the 500w entry will be selected.
Very interesting. I had no idea this is how the source was chosen. I'm finding it very difficult to test responsive images because I don't know what the expected behaviour is, so I'd love to learn more about how source selection works exactly, in Blink's case.

How would I calculate the first breakpoint at which the 1000w entry would be selected? In testing, I can see it is first used when the viewport reaches 354px, but I can't understand what the calculation behind that is. How did the browser decide to use the 1000w srcset entry from a viewport width of 354px onwards?

Comment 5 by f...@opera.com, Nov 23 2017

That choice follows from what I wrote above (sqrt(...)), what you can "always know" - i.e is essentially specified - is that the selection is based on the "pixel density" (computed or specified.)
In this particular case the densities will be computed based on the specified width selectors.
When selecting, Blink will first find the first entry whose density is >= the DPR. Then based on that entry and the one before it (assuming one exists), it will compute the geometric mean (the sqrt(...) expression above) of the two densities. If the DPR is greater than (or equal) to that mean it will pick the entry with the higher density, else it will pick the "previous-highest" density. There some additional logic though for DPRs < 1, in which case the higher density will be selected unless the previous happens to be an exact match.

So as viewport width increases (from 300) the entries ("500w" and "1000w") will get lower densities ("starting" at 1.66... and 3.33...) and hence the mean will approach sqrt(2) as the viewport width approaches 500.

So, at 354 you get a mean = sqrt((500 / 354) * (1000 / 354)), which is just below 2. (353 is just above 2.)

So for a pair of images with width descriptors width1 and width2 at a DPR dpr, you could find the breakpoint between these two as:

breakpoint_width = sqrt((width1 / dpr) * (width2 / dpr))

which in this specific case [sqrt((500 / 2) * (1000 / 2))] yields a breakpoint width of ~353.6. I guess could describe that as the geometric mean of the widths in CSS pixels. I don't think it would generalize to "mixed" descriptors.

Hope that helps (and isn't too overwhelming.)
Thank you very much for explaining that so clearly. I've used width descriptors across many sites, including theguardian.com and unsplash.com, and I'm only just learning this.

Are you aware of any tools or resources that help understand exactly how browsers calculate which source is used?

Separate from the discussion, I think the dev tooling around responsive images could be much better. We haven't seen much improvement since responsive images first landed in browsers. :-(

Comment 7 by f...@opera.com, Nov 23 2017

Status: WontFix (was: Unconfirmed)
I'm afraid I'm not aware of any resources that detail the exact implementation details. In a sense that's as intended (i.e it would be bad to tailor to a specific implementation), but maybe frustrating?
I'll resolve this now, but you can take a look at/star  issue 415147  for DevTools improvements related to responsive images in general. (Feel free to drop any ideas you may have in there.)

Sign in to add a comment