78 comments

[ 0.19 ms ] story [ 241 ms ] thread
I like the concept, but the syntax feels awkward, clunky and very specific.

Why not repurpose the media attribute from style tags to all other tags?

Because it is way more verbose and does not address the pixel density case.
But pixel density is a property of the media, which should be dealt with by media queries.
Querying the pixel density of the device is not the same as describing the pixel density of the resource. This has been a common misconception in the discussion of this feature.
Apologies - I misunderstood the proposal. However, what is the pixel density of a PNG?
What it's representing is not necessarily an intrinsic property of the image but rather the intended pixel density for presentation. Say I have a 600x200 PNG which fits my design for normal resolution displays where 1 CSS pixel = 1 device pixel (which is most current laptop screens, for instance). But then I'd like to take advantage of the extra resolution on a device that displays at 1 CSS pixel = 2 device pixels, such as a retina display iPad. So then I get a 1200x400 version of the same image (perhaps both downscaled from a super high res original) and serve it as the 2x image. It will take the same logical space in the layout but provide extra quality on a higher resolution display. There's no need to do anything special to the PNG.
Awesome reply. I now understand. This is still a property of the media though.
> the syntax feels awkward, clunky and very specific

Yeah, stuff like "2x 100w" looks a bit like magic numbers[1]

Also there's potential for confusion in 'x' - does it mean X as in a co-ordinate i.e. width, or zoom? I'd rather see something more verbose like this:

    <img src="foo.jpg">
      <set src="foo1.jpg" width="100">
      <set src="foo2.jpg" density="2">
    </img>
Yes it's more wordy to write, but you read code more than you write it so it makes sense to optimise for readability over byte-shaving.

[1] http://catb.org/jargon/html/M/magic-number.html

There are certainly other ways to do it, but this particular way won't work. <img> was historically a "void element" in past versions of HTML, and past browsers, so it can never have child elements.
We cannot change the way <img> is parsed. See e.g. http://software.hixie.ch/utilities/js/live-dom-viewer/ for the tree you get with that markup. It's not what you expect.
Fair enough, but that is a technical limitation which is trivial to get around:

    <setsrc>
      <img src="foo.jpg">
      <set src="foo1.jpg" width="100">
      <set src="foo2.jpg" density="2">
    </setsrc>
Always be wary of allowing arguments that hinge on "it's not technically possible" to shut down good ideas.
FTFY

    <imgset>
      <img src="foo.jpg">
      <img src="foo1.jpg" width="100">
      <img src="foo2.jpg" density="2">
    </imgset>
Not a good idea. Browsers that do not support imgset would show all three images using that syntax. A new element name like "<set>" would be ignored by them.
CSS to the rescue

    imgset img{display:none;}
    imgset img:first-child{display:block;}
Same with modern HTML5 tags, modernizer or any other tool would handle that for you.
Not really, what about browsers that don't support first-child? Backwards compatibility is important.
I think lots of informal URLs consist U+002C COMMA character (,)

Why not <img srcset="url_1" srcset="url_2">? Is this against SGML syntax?

That is against sgml syntax, yes.

There must be at least one height / width / pixel density descriptor for each url, so if you see a comma before the url ends, you know it must be part of the url.

Why not like the video-tag

<img>

<source src="house-hd.jpg" width="100px" height="200px" density="2x" />

...

</img>

Or something like that.

See necolas comment above - ie the propose picture element.
> "2x" means "maximum pixel density of 2 device pixels per CSS pixel"

I don't understand why that's maximum pixel density and not minimum pixel density.

If I'm using a super-retina device with 4x pixel density, surely it's better for me to get the 2x image than the default (presumably 1x) image?

Previous discussion about this by developers (170+ comments) who have been discussing Responsive Images in a W3C Community Group - http://www.w3.org/community/respimg/2012/05/11/respimg-propo...
The only problem with the <picture> element is how to address backwards compatibility? The srcset attribute is backwards compatible because old browsers will just ignore srcset and use the src, but old browsers will ignore the <picture> element completely -- how do you get something that works for older browsers but also works for new browsers as well?
The <picture> approach also has a sort of solution for degrading gracefully in older browsers. You can nest an <img> in your <picture>. Newer browsers are supposed to ignore it, older browsers would ignore the surrounding <picture> element instead.

I think there are other good reasons to prefer the srcset approach, but not this one. The email here provides motivation: <http://lists.w3.org/Archives/Public/public-whatwg-archive/20...;

Unfortunately, at the time when Ian didn't seem to care about the issue of responsive images, I asked him about the possibility of using the existing `<img>` element and he said it was pointless to try and modify existing image parsing. Forget it.

Now, he decides that actually this is the way to go. Frustrating.

For reference, in the email linked above, Ian Hickson said:

> So why not just give the UA the characteristics and a template to use to build the file names itself? That way we still give the UA all the same information, but it is much less verbose and still solves all the same use cases. Thus:

   <img src="face-600-200@1.jpeg" alt=""
        src-template="face-%w-%h@%r.jpeg"
        src-versions="600x200x1 600x200x2 200x200x1"></code>
This doesn't modify parsing. Modifying parsing would be something like allowing <img> to have child elements. Adding extra attributes to an element requires no changes to the parser.
Here's an interesting example with <img srcset> http://junkyard.damowmow.com/507

When I saw the last line in the doc linked above, I realized that <img srcset=""> is probably optimized for adding one (1) "retina" image for iPhones and other high-DPI devices.

Better than this specification hassle is this solution:

The browser should send the density of the screen in ppi (calculated by the screen resolution and the screen information provided by the OS) together with all the other standard stuff like OS, screen resolution, etc.

With this information the server can decide which images to send.

No, this won't work in the wild.

It breaks caching completely.

It requires scripting just to serve an image.

The same url can have different data - imagine if you resume downloading a file, only to suddenly have a different file.

I disagree. Caches would have to be intelligent. Remember they already have to pay attention to language headers etc. URLs represent a conceptual resource, rather than a single file.
Caches (proxies) already exist. You don't have the option of reprogramming them for this new header.
Part of the problem here is that there are a wide range of pixel densities. The server could choose to display the same image for some range of values but trying to get a caching proxy to sort this out is highly nontrivial.
Screen PPI (in physical pixels per physical inch) is not the relevant consideration - device pixels per CSS pixel being something other than 1 is the case you care about. And the browser needs to know the intended resolution of the image so it can tell whether to downscale it.
Web servers shouldn't need to rely on any other information than the URL in order to serve the right content. This keeps the simple use cases simple, as the URL directly translates to a file on the server. Otherwise every web werver in the world would need some special new logic for choosing different files.
This is silly and makes things way more complicated than they need to be.

We have HTML tags, to which we can apply attributes directly via blah=blah syntax

Or we can add attributes by making a style attribute, and using css syntax inside of it.

Or we can have a space separated list of class names, and have attributes applied to an element externally by a CSS stylesheet.

Or we can have an ID, and apply attributes using javascript.

We can apply attributes with http headers, and the browser can negotiate the resource with http accepts and quality parameters.

We have video, audio, and object tags that can all have child elements.

We have query parameters and fragment selectors, and path parameters, and post parameters and accept parameters for negotiating and selecting content from a server. (Designed to include ampersands which have to be entity encoded when used in HTML!)

We have all these sophisticated overlapping complicated mechanisms for attaching attributes to elements in a webpage. We have huge pieces of software for parsing through this poorly thought through mess.

But no, not a single one of these is good enough for this problem. LET'S INVENT A NEW SYNTAX AND ADD TO THE HEAP OF IDIOCY.

From an implementation point of view, putting everything in a single attribute is way simpler; the design of <video> is quite problematic. The reason is that with a single attribute everything can be processed atomically. With a design based on multiple elements things can happen between elements being processed, creating many more edge cases.

Although in general things that make authoring easier are preferred, designs that are easy to implement in a bug-free way are generally preferred over designs that are complex and likely to lead to interoperability issues. After all, having to fight implementation differences is a rather common complaint about the web platform.

It also hasn't been clearly demonstrated that multiple elements are easier to work with. They are more familiar, but significantly more verbose. I don't know how that plays out in practice.

I gave you a whole list of options but you only focus on these two. why?
Because I was making a specific point about the implementation complexity of things that depend on attributes vs things that depend on many elements.
And even if what you say about nesting is true- It's already a part of the standards for video, audio, and objects. It's not like we can change our minds about those. So we make the whole language inconsistent just because?
Using CSS means you have to specify image locations in two places, with potentially different base URLs.

Using Javascript means you have to load scripts before the img tag, which can hurt performance.

Using http headers or a special URL format makes working with CDNs more difficult.

This is actually a tricky problem to solve and it looks like the authors have considered some of the above problems.

(I still hope they change it. Nested elements might be a way to go.)

wait hold on how does having a query string in a url make CDN's more difficult?
You would need to turn on caching on your query strings in order for this idea to be useful with a cdn (ie, both http://example.org/image.png?size=big and http://example.org/image.png?size=small would need to be cached by the cdn). The issue is if you use some sort of user tracking, or rss feed, or anything that appends unique data to the end of the URL (so http://example.org/image.png?size=small could become something like http://example.org/image.png?size=small&user=19hv839&...). At that point, every single person is getting the uncached version of the site, since their unique url was never cached before. Its not difficult to configure this sort of thing by any stretch of the imagination, but it does add another step.
why is your user tracking appending data onto the end of a CDN image? This hypothetical web site makes no sense.
The last time I had to deal with this it was a result of links to a site from an email being attached to the user it was sent to (eg example.com/?email=foo@bar.com). It was not a wonderful example, just a quick one. The moral being by caching query strings you risk needing to parse the ones being passed to ensure there in not unnecessary caching.
This use case seems abusive to me. I don't mind breaking abusive use cases.
Neither did XHTML.

Web Standards work requires you put up with a ton of really stupid things that people have been doing for a long time.

I don't mean abusive in the sense that it's using technology in a way it was not intended to be used. I mean abusive as in actively harmful to the user's interests and privacy.
most of your suggested alternatives are worse
I don't care if the syntax is a bit unsightly. Let's just get this into shipping browsers as soon as possible. It's a major requirement for responsive design and this has good fallback behaviour. We can all just stick to 'mobile first' design and a .js polyfill shouldn't be hard.
Or, here's just a crazy out there thought. What if we save our images in high res progressive format, and program the browsers to stop downloading the images as soon as they've acquired enough resolution? Caching can be done with http range requests. Older user agents just end up downloading larger images than they wanted. Javascript and server script can use the JPEGtran library to retrieve lossless low res versions of jpeg images. Similar things could be done with png. No modifications to any standards need to take place.
Is there a way this can take place entirely server side?
sure, it would be simple enough to copy what was done with the server side image maps thing, and define some query parameters that get requested along with the image. So each different size gets its own url and proxies and caches are happy. servers that don't support it just serve a normal image. a tiny bit of javascript can polyfill it in now. today.
That is a very appealing design, but sadly it doesn't address all the use cases. In particular one thing that people want to be able to do is to display a different image depending on the viewport dimensions, for example a closer crop on a small screen compared to that shown on a larger screen.
what is stopping this approach from addressing that use case?
No file format exists which supports this use case.
I wasn't aware that you could specify completely different images at different resolutions.
We switched slightly midstream and we are now talking about an "entirely server side solution", if you scan back a few posts up. It's fairly trivial to do image processing on a server and cache the results based on the URL
i wonder if you could do it with separate frames of a GIF? there's no reason they have to be played as an animation. (they don't even have to be the same size as each other or the logical screen, afaict.)
I don't see how the client could selectively download frames. GIF isn't really the nicest file format anyway.
can you fetch arbitrary byte ranges over http? i don't know the details of the GIF chunk format, but often there's a header or something that you could use to calculate what other part of the file you want.

(yes, this is almost certainly a terrible way to implement it, but i was curious as to whether it could be shoehorned in.)

You can, but this is server dependent and not possible with the GIF format. If you were to construct a format where this is possible, this would mean a minimum of two HTTP requests and quite possible three since the header would have to be of variable length.

Additionally, trying to get browsers to consistently implement something of this level of complexity sounds dangerous.

Looks like a horrible solution which will add bloat and complexity to a webpage.

I would rather see a solution implemented with CSS or even a meta tag.

<meta name="srcset" content="2x=HD; 100w=phone; 100w 2x=phone-HD" />

The above example is exactly the same information as in this link. However it is expressed in one place and thus is far simpler. The only reason to do this per image would be if you different naming conventions for individual images.. which would just be silly.

You could then have a nosrcset attribute which you can add to images which do not have high-res versions. This would save an http request.

An alternative, completely server-side implementation: http://adaptive-images.com/

It takes the approach of setting a cookie when the page first loads with the viewport size, determined through media queries. Every request to the server then includes this cookie.

When an img is requested (as an <img> tag or through CSS background-image) the cookie is read to determine the viewport size of the client. The PHP script then serves up the most appropriate image size to the client.

The only thing you really need to do is add the .htaccess rule (to intercept image requests and route them through the PHP script), the php script itself and the highest resolution you need for each image. The script takes care of scaling down the image for smaller screens, caching them for later use.

I like the way this requires nothing on the client side, other than a cookie being set. All the heavy lifting is done on the server.

I believe this should be moved to the stylesheet. We already have ways to determine media/viewport/device/orientation etc so adding different imgs would be a no brainer.

Bonus point, less cluttered HTML.

That would mean the browser couldn't start downloading any image before it had downloaded and parsed the stylesheet. Or that it would download all images and the entire point of saving bandwidth is lost.
Downloading all images is out of the question. You use the most commonly used image as default and when the stylesheet is done you download whatever img is needed.

Or, you use the newly minted 'defer' (I just came up with that) attribute to let the browser know not to download anything until the stylesheet is parsed.

    <img src='myhugeretinapic.png' defer>
Responsive images are obviously needed but this syntax is noisy and confusing. Adding info after the file extension would make it too easy to overlook.
I agree that the syntax isn't great, and a corresponding set of CSS rules would be welcome, but this does solve a problem.

What I'd love to see is something similar for bandwidth sets, so lower bandwidth connections can be sent lower quality images. And then for both features to be made available for video tags.

This really feels like the wrong approach to me - like this will lead to "best viewed with iPhone 5" pages.

Whilst there will be ways to automate the setting of such img srcset attributes based on the device (eg the PHP method mentioned that relies on a cookie) this sort of tailoring for specific device [characteristics] seems wrong somehow.

IMO this would be better handled by devices declaring their preferred viewport and/or pixel density just as they declare language preferences now, ie browser headers. Then the server can be set to send different images based on the header values and we don't have to worry about having a massive "srcset" attribute on each image tailoring to 500 different device variants. A server config would specify what viewport ranges to use and tell the server how to modify the images sent (or modify the path, or modify the location - eg switch an image with a folder called image.jpg and have filename tagged images for the different variants handled).

Perhaps this seems hacky too ...

In any case the SRCSET attribute proposal here looks short-sighted and hackish to me.

(comment deleted)
Yeah, the srcset for every device type on every single image seems excessive. I was hoping we could take advantage of file naming conventions and define a way for user agents to request 'filename' + 'variant key' + 'filename extension' instead of the 'filename.extension' file in the src attribute when it wants non-1x images, where 'variant key' is something like "_2x" added to the filename for 2x images. Then you could just flag img tags as having 2x available boolean. I don't think whatwg likes the idea of file names as metadata, though.