When Apple announced the first “Retina” HiDPI device, the iPhone 4, it set into motion a slow (slower than I expected, anyway!) migration away from a web on which it was safe to assume every client had roughly the same screen resolution, towards one in which the resolutions of some clients would be so much higher as to warrant distinct image resources.
From a HiDPI device, it’s obvious to most people when a site has taken care to ensure that all the images are suitably high resolution to look sharp on screen. Sites that are not updated look blurry if not downright pixelated, and really take the shine off these fancy displays.
So it seems obvious to me, and should seem obvious to you, that if it’s at all feasible, every web publisher should ensure that her or his site renders beautifully on a HiDPI device. But how feasible is it, really?
Solutions in 2010
The problem in 2010 was that HiDPI seemed to take the web by such surprise that there was no drop-dead stupid way of updating a web site so that it served higher resolution files to the new devices while continuing to serve smaller images, which were also by definition a better fit, for lower-resolution screens. An undoubtedly non-exhaustive list of solutions advised at the time were:
- Serve @2x images. Where you used to have a 100×100 pixel JPG, serve a 200×200 JPG but keep the width and height at 100. It works as expected for older devices, but newer devices with reasonable browsers will take advantage of the extra information density to draw the image with greater precision. The main downside to this approach was that even older devices would be forced to download the larger, higher-resolution image files.
- Use CSS background images. This approach took advantage of the ability for CSS to specify that specific CSS rules should be applied only on devices where the ratio of pixels to screen points was e.g. 2 instead of 1. Because the CSS would be evaluated before any resources are loaded, using this technique would allow a browser to download only the image suitable for display on the current device. The main downside I saw to this was that it encouraged moving away from semantic “img” tags and towards using e.g. div tags that just happen to behave just like images. Things tend to go to hell when printing a page that uses this trick, and I have to imagine it isn’t super friendly to screen-reading technologies.
- Use JavaScript hacks. I say “hacks” with a careful tongue, meant to express both disdain and admiration. Actually, I don’t know how many bona fide solutions there were in the early days, but I seem to recall people talking of dynamic scripts that would rewrite the “src” attributes of image URLs depending on whether they were being loaded on a HiDPI screen or not. The downsides here are that is feels super fiddly, and there were questions, borne out as justified I think, as to whether the tricks would work universally or not.
I jumped to update most of the Red Sweater pages. Why? Mainly for the reasons I listed in Target The Forward Fringe:
HiDPI customers may be a fringe group, but they are a forward-facing fringe. They represent the users of the future, and the more we cater to them now, the more deeply embedded our products and designs will be in their culture. The future culture.
Great thinking, Daniel. Only, in spite of more-or-less supporting Retina very early on, I never really got good at it. I embraced a combination of “just serve @2x images” and “use CSS background images.” But both solutions have bugged me, and made it less fun to change anything about the graphical make-up of my sites. Thus, I have mostly adopted the “if it ain’t broke” approach for the past 4 years, and that has been fine.
Except no, it hasn’t been fine. Because it is broke. Only after finally getting my first Retina MacBook Pro earlier this year have I finally found myself in front of a HiDPI browser frequently enough to become truly judgmental of the LoDPI web. And wouldn’t you know it, one of the offenders is none other than the Red Sweater site. The main page and product pages all sport fancy HiDPI graphics of the application icons, but incidental badges and, worst of all, screenshots of my apps are fuzzy when viewed on a HiDPI Mac. The very “forward fringe” I’m supposed to be catering to will not be so confident of that fact if they rely solely upon my screenshots. So this morning I took to the long-postponed task of correcting my Retina ways.
Solutions in 2014
Surely in 2014, having had four years to bake, the methods for supporting HiDPI on the web will have gelled into a few no-brainer, 100% effective techniques? I had heard a few things over the years about image sets, picture tags, etc., but nothing really jumped out as being the obvious way to support Retina. That’s annoying. I even took to Google and tried searching for definitive rundowns of the 2014 state of the art. Admittedly, my Google-fu is weak (does adding “site:alistapart.com” to any query count as deep-diving in the web realm?), but I wasn’t turning up anything very promising. I took to Twitter:
Any web design friends have up-to-date advice about handling Retina on the web responsibly? Can I just use srcset and be "good enough" now?
— Daniel Jalkut (@danielpunkass) September 29, 2014
My reference to “srcset” alluded to my barely understood impression that a smart-enough browser would interpret the presence of a “srcset” attribute on img tags, and use the content of that attribute to deduce the most suitable image resource for the HTML view being served.
Unfortunately I didn’t get a definitive response along the lines of “you should go read this ‘The 2014 Retina Web’ article.” I’m assuming that’s because it’s really hard to pin down a definitive approach when so many different people have differing priorities: how much effort do you put into supporting older browsers, how important is it to minimize bandwidth costs, are you willing to take on 3rd party JavaScript libraries, yadda, yadda, yadda.
In the absence of such an article, I guess that’s what I’m trying to approximate here. This is for myself and for all my peers who have not paid a ton of attention to the state-of-the-art since 2010, and who would at least set themselves down the path towards making an informed decision. My take thus far about the rough approach to the choices we have today is probably all wrong because I just learned most of it 5 minutes ago, but because I think I would have nonetheless benefited from such a rundown, here it is:
- Keep doing things the 2010 way. That is, if it actually ain’t broke, or you actually don’t care.
- Use srcset and associated technologies. These are specified in the W3C’s HTML draft standard as the new “picture” tag and extension to the “img” tag with attributes such as srcset. To answer my own question “can I just use srcset?” I think the answer is more or less “yes,” as long as you don’t mind degrading to a lower-resolution experience for any browser that doesn’t support the new evolving standard. And I’m not 100% sure yet, but I think I don’t mind.
- Use a polyfill. I just learned that a polyfill is a fancy word for a JavaScript library specifically geared towards providing a compatibility layer such that older browsers behave even when you use newer web technologies. I think the gist of this approach is to more or less use the W3C draft standard features including picture tags and srcset attributes, but to load a JavaScript library such as Picturefill to ensure that the best possible experience is had even by folks with clunky old browsers.
- Use 2014 JavaScript hacks. You could argue the polyfill approach is also a hack, but distinct from that is a popular approach in which a robust library such as Retina.js is used, not to facilitate the use of any kind of semi-standard W3C-approved approach, but to simply get the job done using runtime JavaScript substitution in a manner that does not require extensive changes to your existing HTML source code. The gist of Retina.js in particular is that in its simplest deployment, it will look for any img tags and replace the src attribute with URL that points to the @2x version of the asset, if appropriate for the screen you’re being loaded on.
Further Reading
My searching and the responses of folks on Twitter turned up some valuable resources that may help to paint a clearer picture of what’s been going on. In no particular order:
- WebKit implements srcset… – Announcement from the WebKit team upon being the first mainstream web rendering engine to support the nascent standard.
- … and it’s a good thing! – Mat Marquis responds to WebKit’s announcement.
- Don’t Use <picture> (most of the time) – Jason Grigsby clarifies the distinction between using picture tags vs. using the extensions to e.g. img tags that the new standards afford.
- Retinafy.me – Reward Thomas Fuchs for having the fortitude to take these questions and authoritatively compile a bona-fide book of presumably authoritative answers.
</pseudofacts>
I want to emphasize that this post is an exposition of a few inklings of truth that I gleaned from surveying the web and some friendly, responsive folks on Twitter. There’s no need to roast me for being wrong about anything here, because I don’t claim to know anything about the topic. Well, maybe 5 minutes worth of research more than you…
Many thanks to @edwardloveall, @tomdiggle, @samuelfine, @josephschmitt, @adamklevy, @octothorpe, @seiz, @nico_h and others I no doubt missed or who chimed in after I published this piece, for responding to my Twitter query and helping me to start painting a picture of the current state of the art.