Skip to main content

Safari 6 and Chrome 21 add image-set to support retina images

By Jason Grigsby

Published on August 14th, 2012

Topics
  • 30 Jan 2013 — This is not a stable specification. It will likely change. Do not use it in a production environment. See Peter’s comment below.
  • 30 Jan 2013 — Per Nicholas Shanks’s suggestion, I’ve removed examples for non-WebKit browsers because we don’t know how those browsers will implement the feature and if the syntax will be the same.

Safari 6 and Chrome 21 added vendor-prefixed support for the proposed CSS4 image-set specification. This proposed specification is designed to support displays with different pixel densities (read: retina displays).

I’ve put together a test page that demonstrates image-set and its syntax so you can see if it in action.

We can already address high density displays using media queries in CSS so why do we need image-set? Good question.

I see two main benefits for image-set:

  1. Unlike a media query, image-set isn’t telling the browser what image to use, but instead provides options. In the future, I hope that someone using a high density device on a slow connection might be able to tell the browser that they only want low resolution images. It would be even better if the browser could be smart about what image to use based on the current network speed.
    The problem with media queries for higher resolution displays is they don’t give the browser any discretion. They say explicitly that if the pixel density equals 1 or 2 or whatever, that the browser should (must?) use a particular image source.
    I realize that right now this benefit is largely theoretical because the browsers that support image-set are simply matching the image source to the display density and not providing any additional functionality. But I believe that providing the browser options and letting it pick the right image is the direction we need to go for different resolutions of the same image.

  2. The various resolutions of the image are all in the same place in your css. When you use media queries to specify different image resolutions, you can end up with the image sources separated by dozens of lines of css which makes tracking down the different image sources more challenging.

Unfortunately, a solution for <img> tags is still a work in progress. Image-set only addresses CSS background images.

Image-set is currently only support by Safari 6 and Chrome 21 using the webkit prefix. It is rumored to be coming in iOS 6. As far as I can tell, no other browsers have committed to supporting image-set and it remains a proposal, not part of the CSS4 spec.

BTW, I found the cascade for the image-set syntax to be interesting. As far as I can tell, the code should look like this:

#test {
        background-image: url(assets/no-image-set.png); 
        background-image: -webkit-image-set(url(assets/test.png) 1x,
               url(assets/test-hires.png) 2x);
        width:200px;
        height:75px;
    }
Code language: CSS (css)

Because the prefix is on the property value instead of the property itself, the cascade looks a bit different than we are accustomed to seeing.

Well, it is prefixed for a reason. It will may change in the future. So if you have a way to change it easily in the future, then it may make sense to throw caution to the wind and start using it. Otherwise, consider using it in less critical places where you can experiment with new technology.

Comments

Andy Davies said:

In the first draft of the css4-images spec color is also included in the image-set notation.

The goal being that the browser can decide it really doesn’t have enough bandwidth to download any image and can fallback to the colour.

It’s in this section here: http://dev.w3.org/csswg/css4-images/#image-set-notation but you’ll see that it’s not final and still up for discussion.

If it’s a useful feature it might be worth letting the CSS-WG know.

Peter Linss said:

Please don’t encourage people to put non-prefixed experimental features in their style sheets. It’s fine to try out experimental features on non-production web sites, and reasonable to try to anticipate other vendor’s experimental implementation and add their possible prefixed versions of the same property or value (note that other vendors may implement different versions of the feature and may have different syntax or behavior).

But putting a non-prefixed version of a property or value (as in this case) into any style sheet when the feature does not even exist in an official working draft of a specification, let alone in any kind of stable form, is flat out wrong. Doing this, and worse, encouraging others to do it too, generates an installed base of style sheets with unofficial properties and values in the main CSS namespace and makes it more difficult for the CSS Working Group and browser vendors to modify the feature as improvements to the feature are developed. This defeats one of the purposes of prefixed identifiers in the first place.

Please wait until the feature is in an official specification that is at least at the Candidate Recommendation stage or has otherwise been blessed by the CSS Working Group as being stable before using it in un-prefixed form in any style sheet anywhere. If you don’t have the ability or opportunity to update your style sheets to add the un-prefixed form when the feature does become stable, then that style sheet most likely shouldn’t be using experimental features to begin with.

Peter Linss
CSS Working Group Co-Chair

* As an example, just this week the CSS Working Group discussed this proposed feature, and the addition of the ‘x’ unit as a synonym for ‘dppx’ is contentious and may very well be dropped in future versions. This would make all of your examples become invalid. If the Working Group drops the ‘x’ unit but the web becomes flooded with the use of ‘1x, 2x, etc’ here, some vendors may find it difficult to drop their support of it. This could very well then prevent the use of an ‘x’ unit that has another meaning in the future (where it may have been much more valuable).

Replies to Peter Linss

Jason Grigsby (Article Author ) replied:

Peter,

Thank you for the note. I’ve removed the unprefixed version from the examples.

I’m very sorry for mixing that up. When I was on the road earlier this year, I saw some discussion of solving the prefixing issue by having vendors support the unprefixed version. Unfortunately, I was in places with spotty networks and didn’t follow up.

When writing my examples, I had thought about the unprefixed version for a moment or two and had intended to look into what had happened with that conversation, but got distracted by the fact it was a prefixed property value and never followed up.

Anyways, thank you for pointing it out. The last thing I want to do is create more chaos.

-Jason

Adrian Trif said:

I think this is just wrong, the future css specification should not target a single case scenario and a single computer manufacturer. Let me explain:

The 1x and 2x cases only apply to Apple devices for now, but when other manufacturers will start launching high dpi screens, the increase in resolution might not be made in exact steps (quadrupling the number of pixels). What if we will see screens out there with high dpi but who increase the number of pixels by a factor of 1.7 or 1.8 compared to HD resolution for example?

The problem in my opinion is to decide what is high enough resolution or dpi and based on that to serve a particular high or low res image. And btw, we always have SVG, maybe browsers should start focusing more on SVG support, a file format that doesn’t need any hand-holding in order to adapt to any high dpi screen.

James said:

This seems cumbersome to me. If the purpose of an image-set is to provide 1x and 2x versions of the same image, why not just have the browser recognize a certain naming convention (like “@2x”) and then pick the right version automatically?

In other words, you’d just write “background-image: url(image.png)” like you do normally, and then if you’re on a retina display, the browser would look for “image@2x.png” and display that instead (if it exists).

It just seems like it’s very repetitive and therefore error-prone having to specify the 1x and 2x versions manually for every single image, when the whole point is that these are the same images, just in different resolutions. And having the browser handle it would then work for inline images, too.

Joel MMCC said:

Another consideration here is that most mobile data plans are not truly unlimited, and impose substantial metered data rates for exceeding the monthly quota.

A 2× image has 4× the pixels and takes up 4× the memory as an uncompressed raster, so serving up a 2× image requires 4× the bandwidth, all else (JPEG compression level, etc.) being equal.

For this reason, most users will definitely want the ability to disable this functionality, sacrificing the sharpest possible images on their expensive HiDPI displays that they spent money on in order to avoid spending even more money more often on bandwidth overage charges.

After all, most “mobile” versions of websites use less bandwidth than the “full” versions by design, not only because of the smaller screens (in phones, not tablets), but also partly for this very reason! HiDPI image support would lead to some mobile websites actually using more bandwidth than their desktop versions!

Most such devices do also work with WiFi, which is not metered (at least not at the device itself nor its network provider — the WiFi service provider, on the other hand…). So, one likely default setting would be to request HiDPI images only if the current connection is WiFi, not 4G LTE or 4G or 3G or EDGE or whatever — not just for speed reasons, but to save money for the device’s owner.

But all of this is missing another aspect of practicality: CMSes! The days of hand-coded single-purposes websites are pretty much over. These days, more and more are using CMSes and similar software such as WordPress, Drupal, Joomla, ZenPhoto, and numerous others. With these, most images will be uploaded by users with Editor privileges but who are not educated in the ways of rasters and pixels and bandwidth. They take a photo with their smartphone camera then post it to the site using a web-based uploading tool, often in conjunction with a WYSIWYG editor of some sort. They neither know nor care about the details of whether or how it gets resized.

I don’t see how image-set would solve that issue. I suppose that the image uploader in the CMS could be updated to do all of this behind the scenes when an editor uploads a photo: save a version suitable for HiDPI, another for normal browsers, another for non-HiDPI small screen mobile phones, and a thumbnail (most generate several sizes anyway, such as for thumbnail, normal gallery display, and full size downloading), and set the CSS accordingly.

It seems to me, though, that it may be better to try to tackle this server-side, perhaps by having a “HiDPI” keyword inserted into the User-agent HTTP header or maybe as a new optional header, and if present and if a higher resolution of a requested image is available, it would automatically serve that instead.

Likewise, we may also need a “LoDPI” keyword to allow user agents to save bandwidth and request images at ½ their stated dimensions (¼ the memory and bandwidth), as an alternative to disabling images entirely to save bandwidth. Small-screen phones might have this enabled by default.

With the existing image-set proposal, this would require a slightly more cumbersome syntax: “0.5x”?