JavaScript Package Offers a Smarter Way to Serve Hi-Res Images

The rise of mobile devices means a return to limited bandwidth, but also gorgeous, high-res displays. Better screens connected to skinnier pipes makes serving images on the web more complicated, but fortunately Foresight.js offers a very clever solution.
Image may contain Electronics Computer and Tablet Computer
The high-resolution web is coming. Photo: Ariel Zambelich/Wired

Given enough time, all simple, already solved problems of the web eventually rear their ugly heads again.

Remember when limited bandwidth was a huge problem? Then bandwidth was infinite. Now it’s a problem again. And that means serving up images is once again a complex problem with no elegant solution. Its seems simple. Websites should serve the right image to the right screen, high-resolution images to high-resolution devices and low res to the rest. But of course it’s not that simple. Factors like bandwidth as well as screen size and orientation complicate the matter considerably.

Arguably the best solution right now is to send low-res images to every device. Sure, your images might look terrible on high-res screens, but at least you aren’t wasting people’s time or worse, costing them money.

While that’s the safest solution for now, the web doesn’t get better if no one takes any risks. Fortunately, until some standard or best practice emerges, we’ll likely continue to see developers pushing the boundaries and discovering new ways to handle the seemingly simple task of serving the appropriate image to the appropriate device.

The latest image cleverness we’ve seen is Adam Bradley’s Foresight.js. Foresight.js is designed to make it easy to serve up high-resolution images to devices like the new iPad, but what sets foresight.js apart from half a dozen other solutions that do the same thing is that it not only checks for a hi-res screen, but also checks to see if the device currently has a fast enough network connection for larger images. If, and only if, your visitor has both a device capable of displaying high-res images and a network connection fast enough to handle the larger file size, are larger images served.

Part of what makes Foresight.js appealing is its use of the proposed CSS image-set() function, one possible solution to the problem of serving up the right image at the right time. The image-set() function, which works in WebKit nightly builds and is under consideration by the W3C, looks like this:

 myselector { background: image-set(url(foo-lowres.png) 1x, url(foo-highres.png) 2x) center; } 

Foresight.js takes the image-set() proposal and uses an ingenious hack to make it work in other browsers: the font-family property. Yes, it sounds crazy. But it works and remains technically valid CSS because font-family allows for arbitrary strings (to handle font names). That means browsers have no problem with a rule like this:

 myselector { font-family: ' image-set( url(/images/foo.png), url(/images/foo_2x.png) 2x high-bandwidth ) '; } 

It’s a hack to be sure, but it’s our favorite kind of hack: clever and functional. Because browsers successfully parse the font-family rule (even if they can’t apply it) the value is added to the DOM and JavaScript has no problem accessing it, which is exactly what foresight.js does.

For more on foresight.js, head over to the GitHub page which as links to plenty of examples uses and copious documentation on the script’s many tricks. Also be sure to read through Bradley’s Challenges for High Resolution Images, which offers some background on foresight.js and the design decisions he made.