[whatwg] img srcset / css image-set issues

John Mellor johnme at chromium.org
Wed Aug 22 04:22:43 PDT 2012

On Wednesday, August 22, 2012, Tab Atkins Jr. wrote:

> On Tue, Aug 21, 2012 at 4:28 PM, John Mellor <johnme at chromium.org> wrote:
> > Take the simple example above where
> > you have the same image saved in 4 sizes -- 320.jpg, 640.jpg, 1280.jpg
> and
> > 2560.jpg, named after their widths -- and you need it to scale across
> mobile
> > and desktop. With my proposed syntax you just declare each available size
> > once, and the browser does the rest:
> >
> > <img srcset="320x120, 320.jpg 1x, 640.jpg 2x, 1280.jpg 4x, 2560.jpg 8x">
> >
> > Whereas using only the w/h and x tokens, to properly support devices of
> > various dppx's you have to use the following 16 entry monstrosity (that I
> > had to generate by script):
> >
> > <img srcset="
> >     320.jpg 400w 1x,
> >     320.jpg 320w 1.25x,
> >     320.jpg 267w 1.5x,
> >     320.jpg 200w 2x,
> >     320.jpg 160w 2.5x,
> >     640.jpg 800w 1x,
> >     640.jpg 640w 1.25x,
> >     640.jpg 533w 1.5x,
> >     640.jpg 400w 2x,
> >     640.jpg 320w 2.5x,
> >     1280.jpg 1600w 1x,
> >     1280.jpg 1280w 1.25x,
> >     1280.jpg 1067w 1.5x,
> >     1280.jpg 800w 2x,
> >     1280.jpg 640w 2.5x,
> >     2560.jpg 10x
> > ">
> >
> > (and in the image-set case, doing this with media queries would be even
> more
> > horrific)
> No you don't.  Just do this:
> <img style="width:100%;" srcset="320.jpg 1x, 640.jpg 2x, 1280.jpg 4x,
> 2560.jpg 8x">

No, that's completely different! See below.

> I doubt this is actually what you want, though - you're probably not
> actually trying to cater to devices with an 8:1 pixel ratio!  (Those
> may not ever exist, even if technology does make it possible - I think
> you drop below human perception about 5x or so.)

This is nothing at all to do with 8:1 pixel ratios (though as a happy
accident my proposal would also automatically scale to pixel ratios that
aren't currently common). If you re-read my original email, you'll see that
I defined "320x120, 320.jpg 1x, 640.jpg 2x, 1280.jpg 4x, 2560.jpg 8x" to
mean that for each alternative image, the browser would multiply the
provided intrinsic size (320x120) by that alternative's 'x' token to
calculate the number of pixels of image data available in each dimension,
then it would pick the one that most appropriately matches the number of
device pixels the image is actually taking up in each dimension.

So for example "1280.jpg 4x" means that this image is 4 times larger than
the given intrinsic width of 320px. So sure, it would be suitable for
display on a hypothetical 4x display at 320px width; but the browser also
knows that it would be suitable for display on a 2x display at 640px width,
a 1.5x display at 853px width, and a 1x display at 1280px width. The
browser simply doesn't have that kind of information with the current
srcset spec, so it is forced to be act more dumbly.

> Let's assume that, instead, you're trying to serve two versions of the
> image: one for small screens and one for larger screens, and each
> version has two resolutions.  In that case, you'd do this:
> <img style="width:100%" srcset="320.jpg 1x 320w, 640.jpg 2x 320w,
> 1280.jpg 1x, 2560.jpg 2x">

But that doesn't work! Let's look at some common devices for which it fails:

    360w 2x portrait Galaxy S III => *2560.jpg instead of 640.jpg!*
    480w 1x landscape iPhone 3 => 1280.jpg instead of 640.jpg
    2560w 1x 30" desktop => 1280.jpg instead of 2560.jpg

If even the author of the spec can't write a srcset that doesn't serve
wildly inappropriate files to today's popular devices, how can one expect
average web authors to write srcsets that properly adapt to future device
categories? Indeed, it's not actually possible to fix that srcset just by
tweaking the thresholds; you have to add additional redundant declarations
(as in my "monstrous" example above).

With my proposed syntax, you just declare the available image sizes, and it
just works, across all present and future devices.

> > The fact that the UA is granted some freedom to fiddle with things
> doesn't
> > change the semantics.
> HTML's algorithm is just written a little differently than
> image-set()'s, but the meaning is identical - UAs can choose which
> resolution version they want based on *any* criteria they choose.

As I said, the fact that UAs have freedom doesn't change the semantics in
the eyes of the author. The description and algorithm in the spec heavily
imply that a typical UA algorithm will be to choose the images with the
smallest pixel size descriptors >= the pixel size of the display. It would
be much clearer if this implication was not made, i.e. remove step 21
completely, change step 24 to read "Remove all the entries in candidates
except the one whose associated pixel density is the best match for a
user-agent-defined value giving the nominal pixel density of the display.",
and change the phrase "maximum pixel density" to just "pixel density" in
anywhere else).

> Once again, using image-set() with MQ is *exactly* the same as the w
> and h descriptors in <img srcset>.
> We needed image-set() for resolution negotiation because you *can't*
> use MQ for that.  Attempting to would have *horrible* usability, as I
> explain in <http://www.xanthir.com/blog/b4Hv0>.  However, there's
> nothing wrong with using MQ for width/height negotiation; after all,
> that's their primary purpose.

Ok, I understand where you're coming from on this point. It still seems a
shame to have different syntax from srcset, and I feel one could justify
making them the same by thinking of w/h in css as a shorthand even though
it duplicates functionality. The benefits would include
- Same syntax.
- Avoid non-locality bugs due to paired image-sets being far apart in the
CSS (changing one image, but forgetting to change the narrower/wider
viewport one, etc).
- Avoid browsers potentially downloading both assets (because typically the
non-media-query one will be provided first, and some browsers might
immediately start downloading it).
- Easier to setup alternative images in a single .style.backgroundImage
from JavaScript (can one even create media queries from JS?), so you don't
have to rely on window resize event listeners.

But perhaps these niggles are best solved with a more general way of doing
inline media queries... is anything in the works?

More information about the whatwg mailing list