Srcset Part 1: Retina images

July 19, 2015

Say hello to srcset and say goodbye to all your worries. Srcset is a new attribute you can use on the img tag. It solves many of the challenges of retina in one fell swoop.

Here’s a quick example of the srcset attribute inside an img tag.

<img src="images/image.png" srcset="images/image.png 1x, images/image-big.png 2x" />

The traditional src attribute still holds the image, which will be the fallback for browsers that don’t undestand and support the new srcset attribute. The srcset attribute then specifies two images. The first url string is followed by a space and then 1x. This basically means, show the first image if the device-pixel-ratio is 1x, or your “standard-pixel-density” devices (not Retina). Whereas the second image is followed by a space and then 2x, which means show this image if the device-pixel-ratio is 2x, or “retina”.

This is one of two ways to use the srcset attribute. The other method uses the W descriptor along with its complimentary sizes attribute. I get in to the W descriptor and sizes attribute in part 2.

We’re using the X descriptor, which refers to the “x” that follows the 1 and the 2. This is the image resolution. You can specify any number in front of the x. For instance, I could use 1.5x, 3x, 4.25x, etc. Not that there are any 4.25x devices that I’m aware of, but theoretically you could use any number, not just 1x and 2x.

My original example can be simplified a little. We really don’t need to specify the image for 1x displays as its already specified in the traditional src attribute. So its a little overkill to specify it again in the srcset attribute.

<img src="images/image.png" srcset="images/image-big.png 2x" />

This simplifies so only the image to be used for retina is provided in the srcset and the regular image is provided in the src attribute.

Device-Pixel-Ratio-based selections

So the x descriptor which is usually used for what the W3C calls “device-pixel-ratio-based selections”, basically means whether or not the device is retina.

However, the W3C goes on to say…

The decision of which image to use is not made purely on the pixel density but also based on the browser’s zoom level (maybe the user wants a more detailed view of the image), the network conditions, and possibly other factors. Network conditions? Yup. This is kind of interesting because what if the user is using an iPad Retina but is on a limited bandwidth network (maybe they are getting a weak wifi signal from their hotel room or are connected to the EDGE network). Then presumably the user agent (aka the browser) will provide the smaller image rather than the larger image as the assumption is that speed may be more important than image quality. Bam.

Also, Scott Jehl mentions in his book Responsible Responsive Design that the amount of data left on your cell phone subscription could also factor into the equation. For example, I may have less than 10% of my data plan left with 8 days left to go. That may trigger mobile Safari to not download the larger resolution images. I don’t think any browsers have implemented anything like this yet.

All that being said, we as developers are relinquishing control over to the browser of exactly which image will be served to our users. The srsect attribute is more like a suggestion or hint to the browser as to which image to use. This may be a difficult thing to explain to the client, your manager, etc. when the high resolution image doesn’t appear on the iPad Retina. I anticipate the future holds some interesting conversations on why this is a good thing. This requires us to have more trust in the browser to make the right decision. This will also increase the difficulty level when testing Retina devices to make sure the 2x image is being served under the right conditions.

Live Example

See the Pen The Srcset attribute X descriptor by Rich Finelli (@richfinelli) on CodePen.

In the above Codepen, I have a basic example. Show the 1x version for all non-retina devices, and show the 2x version for retina devices. The spec says zoom level is factored in, and from what I gather in Firefox (I’m using 38.0.5) and Chrome (41), if I zoom in to 200% I get the 2x version, provided that I refresh the browser after zooming. In fact, Chrome starts showing the 2x version of the image at 150% zoom level, and Firefox starts showing the 2x version when zoomed in as little as 110%!

Weird Issue

I hesitate to bring this up, but I’ll just say it. I was seeing some buggy behavior in Chrome when testing on my non-retina Macbook Pro where I was always getting the 2x version of the image. I was chalking that up to 1 of 2 things. One – Chrome was factoring in that I have very good internet bandwidth and is reasoning, why not serve the bigger image just in case this fella wants to zoom in on it. Or two – there was a bug in Chrome 41. I tried to test this theory by walking my laptop down the street away from my router, refreshing the Codepen as I went. However even when I was barely hanging on to the WiFi signal I was still getting the 2x image in Chrome. Although, I did accomplish one thing. I certainly was looking really odd walking down the sidewalk with my head buried in my laptop! Anyway, that issue stopped happening a few days later. I’m still on Chrome 41. So not sure how to explain the buggy behavior but hopefully it is in the past now.

Pontential Problem? Nah.

Also mentioned in Scott Jehl’s book, Responsible Responsive Design, is that using the src as a fallback with srcset could potentially result in a double download in browsers that support srcset! This would take using srcset from being a very attractive and viable option to pretty much a deal breaker. A double download though seems odd to me because browsers that support it should be smart enough to not download what’s in the src attribute if a srcset attribute is present. Also, Google is really pushing for developers to use srcset as a way to optimize performance on HiDPI screens. In fact, they specifically mention that this isn’t a problem:

The last part, “…the comma-separated list of image/conditions is parsed prior to making any requests” cements it that (in Chrome at least) the image specified in the src attribute is not being downloaded if the srcset attribute is present. Potentially though this could be an issue in mobile Safari and other browsers. I have not gone that far quite yet in my research to determine this.

Conclusion

Use it to make your sites retina-ready on the majority of HiDPI devices out there. Safari iOS starting at 8.1 supports the srcset attribute so you’ll be getting your HiDPI images served to most iPad Retina’s provided that they’ve updated to a more recent version that supports it. Also the retina screen that ships with iPhone 6 and 6 Plus also ship with iOS 8. If I wanted to make a really killer argument I would create a matrix table that cross-references HiDPI devices to popular browser usage on those devices, and the browser support for the srcset attribute. My theory is that an overwhelming majority of devices that are HiDPI will have a browser that supports srcset. The best I can do for now though is point you to the caniuse.com browser support table. As you can see, most browsers are supporting it.

Mastering CSS: Book by Rich Finelli
Mastering CSS, the Book! Flexbox, Layout, Animations, Responsive, Retina, and more!
Mastering CSS, 2nd Edition, video course by Rich Finelli
Mastering CSS, Second Edition: 47 videos on how to make websites like a boss! Flexbox, Animations, Responsive, Retina, and more!
Back to top