I spent a chunk of time in the afternoon going over the thorny challenges of responsive images. Jason has been doing a great job of rounding up all the options available to you when it comes to implementing responsive images:

Personally, I have two golden rules in mind when it comes to choosing a responsive image technique for a particular project:

The small image should be default.

Don’t load images twice (in other words, don’t load the small images and the larger images).

That first guideline simply stems from the mobile-first approach: instead of thinking of the desktop experience as the default, I’m assuming that people are using small screen, narrow bandwidth devices until proven otherwise.

Assuming a small-screen device by default, the problem is now how to swap out the small images for larger images on wider viewports …without downloading both images.

Yoav Weiss has been doing some research into preloaders, cookies and race conditions in browsers and found out that in some situations, it’s possible that images will begin to download before the JavaScript in the head of the document has a chance to set the cookie. This means that in some cases, on first visiting a page, desktop browsers like IE9 might begin get the small images instead of the larger images, thereby violating the second rule (though, again, mobile browsers will always get the smaller images, never the larger images).

Yoav concludes:

Different browsers act differently with regard to which resources they download before/after the head scripts are done loading and running. Furthermore, that behavior is not defined in any spec, and may change with every new release. We cannot and should not count on it.

Don’t get me wrong: using a service like Sencha.io SRC (formerly TinySRC)—which relies on user-agent sniffing and a device library lookup—is a perfectly reasonable solution for responsive images …for now. But I wouldn’t call it future friendly; quite the opposite. If anything, it might be the most present-friendly technique.

One issue with relying on user-agent sniffing is the danger of false positives: a tablet may get incorrectly identified as a mobile phone, a mobile browser may get incorrectly identified as a desktop browser and so on. But those are edge cases and they’re actually few and far between …for now.

The bigger issue with relying on user-agent sniffing is that you are then entering into an arms race. You can’t just plug in a device library and forget about it. The library must be constantly maintained and kept up to date. Given the almost-exponential expansion of the device and browser landscape, that’s going to get harder and harder.

Disruption will only accelerate. The quantity and diversity of connected devices—many of which we haven’t imagined yet—will explode, as will the quantity and diversity of the people around the world who use them. Our existing standards, workflows, and infrastructure won’t hold up. Today’s onslaught of devices is already pushing them to the breaking point. They can’t withstand what’s ahead.

So while I consider user-agent sniffing to be an acceptable short-term solution, I don’t think it can scale to the future onslaught—not to mention the tricky issue of the licensing landscape around device libraries.

There’s another reason why I tend to steer clear of device libraries like WURFL and Device Atlas. When you consider the way that I’m approaching responsive images, those libraries are over-engineered. They contain a massive list of mobile user-agent strings that I’ll never need. Remember, I’m taking a mobile-first approach and assuming a mobile browser by default. So if I’m going to overturn that assumption, all I need is a list of desktop user-agent strings. That’s a much less ambitious undertaking. Such a library wouldn’t need to kept updated quite as often as a mobile device listing.