December 2014

Volume 29 Number 12

Cutting Edge : Effective Image Handling in Responsive Web Sites

Dino Esposito | December 2014

Dino EspositoResponsive Web design (RWD)—creating one unique Web experience through a fluid and adaptive Web layout—is undoubtedly one of those milestones that will change the flow of things in the real world.

As a Web developer, you must be ready to live side-by-side with a given fact and its exact opposite. On one hand, RWD is a de facto standard. It’s becoming a must-have for all Web sites. On the other hand, RWD is still an in-progress methodology, with best practices still being defined and redefined. In this article, I aim to provide a quick snapshot of the state of RWD, focusing on the most critical aspects: overall performance and particular image handling.

RWD Performance

The primary purpose of RWD is to make content easy and enjoyable to consume on devices, regardless of size and shape. So far, so good, but how would you do that?

RWD requires quite a different approach to project approval and development. The canonical visual checkpoint when your customers look at static mockups and give you the green light is a much less defined step. Instead of static mockups, you’ll likely present wireframes. Overall, a responsive site is easy to sell to customers, but it’s challenging to explain why it ultimately turns out to be more expensive than having a classic non-responsive site.

A few years of experience have helped consolidate a few practices and a few frameworks such as Twitter Bootstrap have emerged to help with the responsive site implementation. But how about performance?

Performance is currently the sore point of RWD. A responsive site works beautifully when viewed through powerful desktop browsers. Their performance, though, tends to degrade when consumed via smaller devices such as smartphones. RWD isn’t effective in the same way for just any type of Web site. A portal of news and videos is easier to reshape to make content usable on smaller screens than a site that has a lot of forms and requires interaction, such as a travel-booking site. In the latter case, the screen size is a more important factor.

The key question to ask a potential customer before starting on an RWD implementation is how much its business cares about the capabilities of the various devices. If devices serve a business purpose such as searching or purchasing products or services, then you can’t just differentiate content based on plain screen width and orientation. A resized desktop browser window and a smartphone may be able to display content using the same layout, but they run on different hardware and have vastly different computing capabilities. If the business cares about the choice of devices, those differences should be taken into careful account before making any decisions.

The One-Site Metaphor

The “one-site” metaphor is at the foundation of RWD: There’s one unique set of content pages, one back-end logic, one URL and one brand. There are two ways you can approach this type of RWD site development. For each view and regardless of the device, you serve the same HTML markup and make a bunch of different CSS files available to the device. Each CSS file is bound to a media query expression the browser evaluates at run time when the window size changes. The applied CSS might change on the fly, which changes the appearance of the content. This approach relies extensively on CSS3 media queries, a World Wide Web Consortium (W3C) standard defined at bit.ly/1oVBf89. Here’s how you would define two CSS files to be applied at two different screen sizes:

<link type="text/css"
  rel="stylesheet"
  href="view480.css"
  media="only screen and (max-width: 480px)">
<link type="text/css"
  rel="stylesheet"
  href="view800.css"
  media="only screen and (max-width: 800px)">

The other option for developing responsive sites involves using CSS3 Media Queries with JavaScript code to appropriately reshape the Document Object Model (DOM). This approach is more powerful because it gives you more control over the layout. It also adds the opportunity to download extra content specific for the screen size. To detect changes of the screen size, you can use either the window resize event or the matchMedia event. The matchMedia event is a JavaScript implementation of media queries. When the browser detects a change in the specified media query, it fires a call to your code:

if (window.matchMedia) {
  mq800px = window.matchMedia("(min-width: 800px)"),
  mqPortr = window.matchMedia("(orientation: portrait)");
  mq800px.addListener(mq800px_handler);
  mqPortr.addListener(mqPortr_handler);
}

When the browser detects a portrait orientation or a minimum width of 800 pixels, the code will invoke your handlers. You can use JavaScript and CSS media queries within the same site. They apply to individual HTML views or pages.

So the key pattern behind RWD is one set of content with multiple views, whether you reshape that using CSS or some ad hoc JavaScript. If you go the CSS route, you’re subject to what you can do with CSS in a Web page. You can move and reposition elements, you can reflow content within differently sized containers, and float blocks of content horizontally or vertically. You can also simply hide unwanted content.

With JavaScript, you can do all of that and then some. You can make more sophisticated changes to the view layout, create DOM subtrees from scratch or download new content from remote endpoints. With CSS, the DOM is the largest possible. With JavaScript, it can only grow to the extent of becoming the largest possible that was designed.

The size of RWD solutions isn’t an issue when viewing sites on desktop browsers. It may not even be an issue on most tablets. Those tend to be powerful enough to run any required JavaScript and are often used through a solid Wi-Fi connection. The issue is having RWD sites on smartphones with 3G connections. In those cases, it’s not so much the amount of markup and JavaScript code, it’s the related events and their impact on threading that bogs things down. The most painful aspect of RWD is images.

Handling Images

The old img element references images. They’re downloaded entirely and displayed as specified by width and height attributes. If you need a large background image for a desktop or numerous large images for a carousel, you can’t simply use CSS to adjust width and height. That would have no impact on the download size. Hiding images via CSS doesn’t help, either, as the image is downloaded anyway.

There are a few tricks you can apply while waiting for a new HTML element to be available. However, a new HTML element is a ways off in terms of widespread browser support. There are some experiments going, but they’re not for prime time yet. The direction seems to be having an element whose structure blinks at the HTML5 structure of the video element, as follows:

<picture>
  <source media="(min-width: 400px)" srcset="foo-sm.jpg, foo-sm-2x.jpg 2x">
  <source media="(min-width: 800px)" srcset="foo-md.jpg, foo-md-2x.jpg 2x">
  <img src="foo.jpg">
</picture>

When using picture instead of img, you provide a range of options for the same logical image. You provide a set of images for each media query scenario and within each scenario you might provide multiple images to address different pixel densities. In that example, when the screen width is at least 800 pixels, the browser might choose a regular image with an appropriate size or a larger copy made-to-measure for a higher density or even to satisfy art direction requirements and provide a different image or a crop of the original image when a given media query kicks in. The embedded img element indicates the fallback and is logically equivalent to what is in use today. You can experiment with this approach using the JavaScript polyfill found at bit.ly/1aVEoxb.

Another approach is to use server-side logic, such as an HTTP handler. The handler will receive the request and decide which image to download. Frankly, this approach can be a challenge. The server-side logic needs some clues to select the most appropriate image. Those clues can only come from the browser and should be put into the HTTP request, whether with a query string or headers. This requires some scripting work to be done when the images are downloaded upon page loading. This is doable, but tricky.

While waiting for the picture element, image size and other aspects of the RWD specification to become standard and available on all browsers (only Chrome and Opera currently provide some support), stop and reflect on the exact problem you’re trying to solve.

As long as the user is on a desktop browser, the size of the image isn’t a big deal. Just point img to the largest one. If the browser window is resized, the same large image is resized. At that point, it no longer has an impact on performance. You want to change an image on smaller windows to focus on particular aspects. In that case, one trick might be to reference the image as the background of a div set via CSS instead of a plain img element. The advantage there is media queries will select just the image you want. You might get multiple images downloaded on the desktop, but that could be a negligible point. There could be other issues with background images if users try to print the page.

Using background images helps when the RWD site displays on mobile devices. Images are guaranteed to be of the proper size. Either way, you need to address the use of images in RWD when you plan to view the site on non-desktop devices.

How would you detect which type of device is being used? Detecting devices isn’t a deadly sin. Reliably detecting devices is difficult, however, and can be a mess if you do it yourself. You can use a popular Modernizr plug-in for some forms of client-side device detection (bit.ly/1tfJhtf). This way, you can programmatically modify the DOM to try to get ad hoc images. That approach is reasonable, but doesn’t scale with the number of devices and may become unreliable at some point. Device detection is a serious matter and requires expertise.

A Look at WURFL Image Tailor

One new interesting approach to image handling is the Wireless Universal Resource File (WURFL) Image Tailor (WIT) component. Backed by the full WURFL engine—the same device detection engine used by Facebook—WIT performs a quick server-side analysis of the user agent. It determines the form factor of the requesting device and serves a resized version of the original image. WIT is a free service that just requires a fix to the image URL:

<img src="//wit.wurfl.io/[full-url-to-your-image]">

You append the full image URL to the WIT Web site URL so you can download the image from the original Web site, resize the image and return pixels to the requesting site. Images are cached on the WIT end. That keeps the number of requests to the bare minimum. A bunch of supported parameters let you control aspects of the resizing such as cropping, dimensions and returned format.

WIT has pros and cons. On the upside, it relieves you of the burden of dealing with multiple versions of the same image. All it requires is a slightly modified version of the URL in the plain old img element. Plus, you can start using it in a matter of seconds.

On the downside, it acts as a proxy and doesn’t specifically address scenarios where you care also about pixel density and not just size. In any case, there’s no reason for not giving it a try. You’ll find it at wurfl.io/#wit.

The landscape of image handling within the context of RWD is fluid. Some compromise between RWD and devices will have to be forthcoming to ensure things work effectively everywhere.


Dino Esposito is the co-author of “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2014) and “Programming ASP.NET MVC 5” (Microsoft Press, 2014). A technical evangelist for the Microsoft .NET Framework and Android platforms at JetBrains and frequent speaker at industry events worldwide, Esposito shares his vision of software at software2cents.wordpress.com and on Twitter at twitter.com/despos.

Thanks to the following technical expert for reviewing this article: Jon Arne Saeteras