Delivering mobile-friendly images
Major considerations
There are three primary concerns when delivering mobile-friendly images:
- Improving clarity and legibility
- Reducing payload size
- Reducing the number of HTTP requests
Improving clarity and legibility
A common practice when mobile-optimizing images is to simply shrink them down to fit the mobile screen. This may work well with many photographs—especially those whose role is to simply embellish a piece of content—but it can have disastrous effects when images contain fine detail or provide information that is critical to the content. The example below shows the rendering of a chart graphic that was delivered to the device using a generic size, then simply scaled by the browser.
Scaled by the browser
The following example shows a chart graphic that has been custom-generated to suit the client’s screen size.
Custom-generated image size
A great example of this problem can be seen in the charts used to display mileage statistics in Mileage Stats Mobile. We generated these charts on the server, but initially chose to deliver a generic size (600 x 400 pixels) that would be scaled up or down using CSS to suit the actual screen size. This resulted in charts that were so fuzzy and pixelated that they were barely legible. The only option to maintain clarity on all devices was to detect each device’s screen size, and use this information to generate an appropriately sized chart. Charts were also styled using a max-width property of 100% to ensure that in cases where the images might be compelled to scale (for example, if the user switched to a much wider landscape mode) they wouldn’t scale any larger than their original size. See Delivering mobile-friendly charts for details.
Reducing payload size
Delivering lightweight images shows consideration for your users. Mobile networks are slower than wired ones, and penetration rates for high-speed data (such as 3G and 4G/LTE) vary considerably, even within developed countries or regions such as the United States. Many users also pay for each kilobyte they download, or are provided with a monthly allowance, and often forced to pay if they go over their preset limit.
Serving lightweight images reduces a user's costs when using your app, but also ensures that your app loads quickly. The attention span of web users is already short; on mobile it can be even worse. Surveys indicate that users expect a mobile site (or app) to load at least as fast (or faster) than it would on their desktop computer at home. So the faster your app, the less likely your users will be to begin hunting for an alternative.
Reducing the number of HTTP requests
An easy way to improve performance in your app is to reduce the number of HTTP requests. As discussed in Delivering mobile-friendly styles and markup, you should be pragmatic when reducing requests and consider the overall impact on the project. If saving a handful of HTTP requests requires weeks of work or causes a major shift in workflow, the additional work may not be worth it.
Luckily, when it comes to saving HTTP requests caused by images, there are several excellent options available:
- Using CSS image sprites
- Embedding images using a data URI
Note
A third option that we will not cover due to poor support is the use of CSS 2.x clipping regions. This technique relies on a much older CSS specification, but is unfortunately poorly supported on certain mobile browsers.
Using CSS sprites
CSS sprites are individual images (such as icons or common brand elements) that have been grouped within a single bitmap image file (called a sprite sheet).
An example of a CSS sprite sheet. All icons are combined into a single bitmap file.
This sprite sheet is then referenced within the style sheet as a background image. Each time one of these images is required, the sprite sheet is repositioned so that only the required sprite is displayed. As all the images are contained within one sheet, there is only one download and one HTTP request.
An example of the use of CSS sprites
The technologies required to use CSS sprites are well supported on mobile browsers, but the technique can require additional markup. Positioning a sprite sheet so that only the desired sprite is visible, either requires sprites to be positioned quite far apart (so that one doesn’t accidentally appear on browsers that miscalculate the position) or, the sprite must be applied to a container element that is smaller than the sprite sheet. This often requires the addition of a <div> element or other non-semantic container (shown in the diagram above as a red, dotted line).
Sprites can also be difficult to use in cases where the layout is flexible because the sprite’s parent container may also be flexible, increasing the likelihood that adjacent sprites may unexpectedly appear due to differences in browser specification and rendering.
For both these reasons, we chose to deliver icons for Mileage Stats using the slightly more HTTP-intensive technique of base64-encoded images.
Embedding an image using a data URI
Data URIs enable you to embed images as raw base64-encoded data, that is then decoded and rendered by the browser. Image data can be embedded directly into an app’s HTML, or referenced within the CSS. In either case, this data is downloaded with the initial application files. The images are then decoded when needed and no additional HTTP requests are required.
Images that have been converted to a data URI are often a bit larger than the equivalent bitmap reference would have been, but the savings in HTTP requests are often well worth the slight increase. Minifying and gzipping markup and styles will assist in reducing this additional weight and is considered a best practice regardless.
.flash.alert p {
color:#d72e02;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAA/0lEQVQ4ja2TKw7CQBRFDx+FIWygGocAj6pmCbiyDlZBaNI94Em6AkioKw4MigRIERBSimDaTMsMTEOveZP5nLnzubUkSahS9UppQFM3EPYac8D5snYN2N0gPsmdSocGMIA+sCx2fgANYRlUzM9USx8l7DU6Ysd+cVVrMATgcdjzOOxUYLcbxJOiQyUMwPJ8LM+nPRrrnDqpUxmohJWQUwRWIiPg83p51+hcDfAWbnL1b2AZGQHv2yBXv0kbPVmRvyCOzsQGdygDXTQJsTw/ax9nUx1rDdKRxU93f1rQw2yQopdKleUf0ctipwQK6Aqz5ORgoH9lG3EnZWBah//oBcbsY/fF+otkAAAAAElFTkSuQmCC)
}
Note
Free online tools are available to generate data URIs. A search for "data uri generator" will provide the most up-to-date list.
Using canvas and SVG
There are considerable benefits to using newer image formats such as canvas and SVG on mobile; however, these benefits may take a few more years to be fully realized.
Scalable Vector Images (SVG) are ideal for mobile as they are often lightweight, and can be scaled up or down with (theoretically) little impact on clarity. Support for SVG is improving, but if your app needs to work on older browsers, you will need a strategy to detect support for SVG, and provide bitmap images in cases where SVG is unsupported). There are also differing levels of support for SVG, even in newer browsers, so it’s important to carefully examine the overall value of using this format for your project.
Aspects of the canvas API are now supported on most smartphone browsers and can be used to generate and style diagrams, icons, and other graphical images. Support for canvas is improving but—similar to SVG—it cannot yet be relied on as a solution on all browsers. Generating complex graphics using canvas can also be time consuming, and extensive testing will be required if supporting many browsers. Tools and libraries are available to assist you in generating canvas drawings; however, many have not been fully tested on mobile.
Delivering high-resolution images
Mobile devices come in a large range of pixel densities (the number of hardware pixels per inch). On high pixel-density displays, HTML text is crystal clear, but bitmap images can look fuzzy if not designed with this high density in mind. If an image has been specified as a background image using CSS, it’s easy to swap it for a higher-density version using the device pixel ratio media query.
An example of this technique can be found in the enhanced.css style sheet. In this case, we use a media query to identify devices with a pixel ratio of two. We then specify a new icon within that media query. The original low-resolution icon (the one we are replacing) was 20 x 20 pixels. The new icon is four times that size, 40 x 40 pixels. We then resize this icon using the background-size property, to fit the original 20 pixel x 20-pixel dimension.
@media all and (-webkit-min-device-pixel-ratio: 2) {
form li.required, .flag {
background-image:url(data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAzElEQVRYhe3YuRGDQBBFwUbBopggWeRKJa69Ztfgud/pqvFm2rbNbuu0YN4f43odLvP2xhpH2e8YyBDIcyDdkddAuiLvAemGvA+kCzINSDgyHUgoMg9IGDIfSAiyDEhzZDmQpsg6QJoh6wFpgqwLpDqyPpCqyDZAqiHbAamCbAukGNkeSBEyBkg2Mg5IFjIWSDIyHkgSsg+Q28h+QG4h+wK5RPYHcoocA8ghchwgu8ixgPwhxwPyg5wOH5gjtE7L2ECjnvirB1jaAyztA7vNWNO+pD0WAAAAAElFTkSuQmCC);
-webkit-background-size:20px 20px;
background-size:20px 20px
}
}
An example of a normal and high-density graphic
Note
Before implementing widespread image replacement for high-pixel-density displays, consider the impact this will have on the performance of your app. Keep in mind that each high-density image is not only crisper, it’s also likely much heavier than the original. The impact of this may be minor if all you’re replacing is a few tiny icons, but replacing much larger images (or large quantities of smaller ones) can add up to a much heavier app.
Summary
When planning to deliver images that meet the performance needs of your mobile app, keep in mind the primary concerns of image clarity, size over the network, and number of network requests. It’s also important to note that there is no one-size-fits-all solution for delivery of images. The method you choose depends upon the type and purpose of the images.
Next Topic | Previous Topic | Home | Community
Last built: June 5, 2012