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 src="images/image.png" srcset="images/image.png 1x, images/image-big.png 2x" />
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
<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
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.
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%!
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.
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.