Responsive images without Javascript

Responsive development owes its roots to the mobile-age challenge of scaling content onto handheld screens. Images are a key focus of many responsive techniques: when a device stops by your website with a 480px screen, wouldn’t it make sense to keep the pictures sharp (and save a bundle of bandwidth in the process) by delivering them at a size no larger than the browser screen?

The catch is that images must still be recognizable to the browser. That means that fudging the original img tag is off the table:

<img src="photo.jpg" alt="A cool image" />

Through HTTP trickery and a little bit of server-side black magic, however, responsive techniques allow the server to complete requests for photo.jpg with a version that is scaled to fit the screen of the requesting device. The typical approach to responsive image delivery uses javascript to calculate the size of the browser window and pass its dimensions (via cookie) to the server. Every once in a great while, however, a user might stop by without javascript support. There’s no reason that they shouldn’t be able to take advantage of responsive images as well, right?

For the purely academic pursuit of knowledge, let’s give it a shot. (You can download a complete copy of the project files here).

The trouble with developing a javascript-free technique is that the server actually has very little knowledge about the browser on the other end. You could probably guess whether a device is mobile or not based on its user-agent string, but that’s about it. That means that the browser’s window size must be identified on the client-side and passed manually onto the server. This is where media queries—those age-old enablers of responsiveness—come in.

/* Desktop */
@media (min-width:1025px) {
    html { 

/* IPads (landscape), etc */
@media (max-width:1024px) {
    html { 

/* Handset devices */
@media (max-width:480px) {
    html { 

Woah–what a hack! We’re pretending that a server-side script (mobile-images.php) is an image and using it to tell the server what size of screen it should respond to. The fake image is being attached to the html selector here, but in practice it should be included under a selector that isn’t so likely to have a background of its own.

The next step is to catch the size parameter passed through the CSS image request and use it to help the server send an appropriate size of image.

Setting up the server

First, download a copy of mobile-images.php and extract it to the root directory of your website. The script contains a (skeleton) helper class for recording the screen size and serving up appropriate images in response. In the default configuration, images are served from the /images directory based on their size. For example, the original photo.jpg might have alternate versions saved as:

/images/photo.jpg          # default/fallback/full resolution
/images/photo-mobile.jpg   # 320px
/images/photo-tablet.jpg   # 640px

The last step is to set up htaccess so that all image requests are routed through mobile-images.php.

RewriteEngine on
RewriteRule ([^/]*\.(jpg|jpeg|gif|png))$ mobile-images.php?image=$1 [NC,L]

Now, whenever the browser asks for an image, the mobile-images script is positioned to send an appropriately sized response.

In conclusion

This is not a front-line technique. Because media queries are a fairly recent addition to the CSS spec, odds are that any browser that supports them will be browsing the internet in a fairly recent way (i.e., with Javascript enabled). That means that a good 98% of the time, Javascript-based techniques for retrieving and resizing images are totally appropriate.

It’s also worth noting that, because CSS background images typically begin loading after the contents of all <img> tags, no cookie will have been set the first time a page loads and, by consequence, all images on the first page a user visits will be delivered at full size.

These shortcomings leave me strongly suggesting that any real use of responsive images starts with a javascript-based solution like those created by:

But hey….a fallback never hurt anyone.