I normally don’t write a post simply to link to another article, but if you’ve enjoyed the things I’ve written about responsive images, you really should read what Eric Portis wrote about Srcset and Sizes.
Eric describes the logic behind srcset and sizes, how they are part of the new picture proposed standard, and how to use them.
A few years ago I wrote an article entitled CSS Media Query for Mobile is Fool’s Gold. It garnered a lot of attention at the time, and I still see people reference it.
I’ve long wanted to write an update to that article, but never knew quite what to say until now. And because one inflammatory title deserves another, read on for why Responsive Web Design is Solid Gold.
Our default approach is now responsive web design
Back in 2010 when I wrote the Fool’s Gold article, our default approach for mobile was to use device detection. If a site was simple and the budget small, we might use responsive web design.
Some time ago our default approach switched. We now treat responsive web design as the default approach and look out for reasons why it won’t work instead of the other way around.
Why did our default approach change? Two reasons: performance and device diversity.
Update on performance
Much of my Fool’s Gold article focuses on performance problems with flexible images and CSS background images. One of the reasons why I’ve had trouble figuring out how to write a follow up is because the performance issues that I raised remain true today.
Let’s do a quick round up of the issues and updates on each:
Perhaps most importantly, most responsive web sites are still far too large on small screens.
So if most of these remain true and most responsive designs are bloated, why has my perspective changed?
Because it is possible to build responsive design responsibly and create fast experiences. The keys to doing so are:
- Build mobile first responsive designs
- Keep CSS background images in scoped media queries
- Implement a responsive images solution
- Handle retina images very carefully and err on the side of performance
If you do these things and do the normal things you should do to make any web page fast, you will have a fast responsive design. It may not be easy, but it is possible.
But what about the fact that most responsive designs are bloated? As Tim Kadlec says, “blame the implementation, not the technique“.
I don’t blame device detection for the many sites that route people to the mobile home page instead of the article they’re looking for. And I don’t blame responsive web design for the fact that most implementations are bloated.
Can a responsive design ever be as fast as a page tailored for a specific device?
Probably not. But the web is a balancing act between many competing interests. A site that was completely tailored for search engine optimization would be unreadable by humans.
By the same token, performance is an extremely important factor, but is still just one of many factors that make a site successful. You can build responsive designs that are fast enough that the benefits of responsive design outweigh the potential performance improvements you might get from separate sites.
Especially when you consider device diversity.
Device diversity makes responsive design inevitable
Let’s assume for a moment that responsive design doesn’t work for your project. So you decide that you’re going to need to build mobile, tablet and desktop experiences. And let’s set aside for the moment the inevitability of new form factors like televisions, watches, etc.
Even in this scenario with different experiences for each of the three major form factors, you’re still going to end up needing responsive design—or at least responsive characteristics.
Yesterday, Samsung announced that it was launching a 6.3 inch phone. The range of screen sizes on mobile phones alone will likely force you to build something that will adjust from the small screen sizes of Blackberry Bolds and feature phones to the mammoth screens of some Samsung devices.
Tablets present a similar challenge ranging from 7 to 13 inch displays (and sometimes much bigger). And we’re all familiar with the large difference between ultrabook screens and cinema displays.
I wrote in much more detail about the impact of device diversity earlier this year and my conclusion that:
Any attempt to draw a line around a particular device class has as much permanence as a literal line in the sand. Pause for a moment and the line blurs. Look away and it will be gone.
So regardless of what techniques you use in addition to it, responsive web design will likely be part of your solution.
What about mobile context?
One of the other points I made in the Fool’s Gold article was related to mobile context. It is something I’ve struggled with for years.
I’m now firmly on the side that there is no mobile context. We have abundant data that shows that people use their mobile devices indoors and for a wide variety of things.
Luke captured it well when he wrote:
But if there’s one thing I’ve learned in observing people on their mobile devices, it’s that they’ll do anything on mobile if they have the need. Write long emails? Check. Manage complex sets of information? Check. And the list goes on. If people want to do it, they’ll do it on mobile -especially when it’s their only or most convenient option.
So Jeremy Keith and Stephen Hay were right. There is no mobile web. Mea culpa.
Still No Silver Bullets
I concluded my Fool’s Gold article by stating the obvious: there are no silver bullets when it comes to adapting our existing apps and sites for mobile screens. At that point in time, people were touting media queries as a quick fix for mobile.
Since then, our profession has learned a lot more about the complexity of designing and building experiences for multiple devices. Now it is generally understood that supporting all the devices that may access our content and services isn’t easy, but that tackling problems that range from responsive images to legacy content management systems are the heavy-lifting that we must do in order to be future friendly.
And despite those challenges, I’m excited about where the web is heading and what we can do with progressive enhancement and responsive web design.
Responsive web design: it’s solid gold, baby. :-)
Last year, I wrote about the challenges of picking responsive images breakpoints and how I found it a nearly unsolvable problem. It has vexed me since.
But I have a new idea on how we might be able to define responsive image breakpoints that is based on a performance budget.
Before I begin, I should note that a lot of this is a thought experiment. I don’t yet know how practical this approach would be.
Brief refresher on responsive image breakpoints
Without going into all of the details about responsive image breakpoints, the short version is that most people are picking the breakpoints for responsive images based on one of two criteria:
- Based on what Scott Jehl referred to as “sensible jumps in file size to match screen dimension and/or density” OR
- Simply matching the image breakpoints to the major breakpoints being used for the design.
While the first method is more efficient and will probably result in better image sizes, my suspicion is that defining “sensible jumps in file size” is so nebulous that most web developers are going to choose to do the second, easier option.
That is unless we can find a formula to calculate what constitutes a sensible jump in file size and that’s what got me thinking about performance budgets.
What is a performance budget?
I’m not sure how long the idea of a performance budget has been around, but I first became cognizant of the idea when Steve Souders talked about creating a culture of performance on the Breaking Development podcast.
Tim Kadlec expanded on the idea in a recent blog post. He cites the BBC which determined that “each page to be usable within 10 seconds on a GPRS connection and then based their goals for page weight and request count on that.”
So that’s the basic idea. Establish a performance budget and stick to it. If you add a new feature to the page and you go over budget, then you have a three options according to Steve (and transcribed by Tim):
- Optimize an existing feature or asset on the page.
- Remove an existing feature or asset from the page.
- Don’t add the new feature or asset.
What is the performance budget for flexible images?
Let’s apply this idea of a performance budget to responsive design. In particular, let’s treat the idea of flexible images as a feature. Because flexible images are a feature, we need a budget for that feature.
And as long as we’re making up the rules, let’s establish a few more hypotheticals:
- The page we’re working with has 10 images on it of varying formats and visual content.
- We haven’t reached our performance budget yet so we don’t have to remove other features, but we still need to make sure that flexible images do not add too much to the page weight.
- We’ve concluded that flexible images can add up to 200k to the page above what the size of the page would be if we provided fixed width images. We picked 200k because it is ~1 second at HSDPA (recent mobile) speeds. And well, 200k is a nice even number for this thought experiment.
- Because this page has 10 images on it, each image has a 20k budget for flexible images.
One thing to keep in mind, 200k isn’t the cap for the file size of all ten images combined. Instead, it is the price we’re willing to pay for using flexible images instead of images that are perfectly sized for the size they are used in the page.
For example, say you had a responsive web page with the following image on it:
That image is 500×333 pixels and 58K in file size.
Now imagine a visitor views that web page and based on the size of their viewport, the image is displayed at 300×200 pixels, but the source image is still the same. The cost of using flexible images is the difference in file size between what the image would be saved and optimized at 300×200 versus the file size of the image downloaded at 500×333.
In this case, I’ve taken that example image and resized it to 300×200 and saved it with the same compression level as the 500×333 image to see what the file size cost is of using that flexible image.
In this example, the visitor is downloading an extra 34k of image data because they are downloading a flexible image instead of downloading one that had been resized to the exact size being used in the page.
Translating the budget into breakpoints
Let’s go back to the page we want to optimize—the one with ten images on it and a total performance budget of 200k for flexible images. How do we translate that into image breakpoints?
Thinking back to the example above, the price for using flexible images is the difference between the size of the file that is downloaded and the size the file would have been if perfectly sized for its use in the page.
Our budget says that we can only download up to an extra 20K per image. Therefore, we need to make sure that we have a new image breakpoint every time the size of the image increases 20K.
We now have a methodology for picking sensible jumps in image file size that is tied to user experience instead of picking them arbitrarily.
Finding the breakpoints
How would this translate into a heuristic that could be used to find the breakpoints? You would need the following:
- What is the minimum size this image will be used at? (In our example, let’s say 320×213)
- What is the file size between breakpoints? In other words, what is your per image budget? (20k for our example)
- A high quality source file to use for resizing.
- Optionally, the largest size the image will be used at. (990×660 for this example).
Once you have this information, the basic logic looks like this:
- Take the source image and resize it to the smallest size the image will be used at.
- Keep the file size of that image handy.
- Start a series of tests that create new image files from the source that are gradually getting bigger.
- Check each image created. If the difference between the file size of the new image and the image file size you stored is less than your budget, discard the new image.
- When you find an image that hits your budget, save that image and replace the previous file size that you stored with the new file size.
- Repeat steps 2 through 5 until you reach either the maximum resolution of the source image or the largest size the image will be used at.
I’m tickled to say that my co-founder John Keith got excited by this idea and built a rough prototype of how this might work.
Using the script that John built, I created a demo page containing ten images. The source images were 990 by 660 pixels and all but one of them were saved as JPEGs at 50% quality. The one exception is a PNG8 image with an optimized color palette.
I tried to pick a variety of images so we can see how each image might have different breakpoints using our budget. Let’s take a look at three sample images.
Time Square — 8 Image Breakpoints
This image has a lot of visual diversity. The variations in colors and textures means that JPEG’s lossy compression cannot do as much without damaging the image quality.
Because of this, there are eight image breakpoints—set at 20k intervals—between the smallest size of the image (320×213) and the largest size of the image (990×660).
Morning in Kettering — 3 Image Breakpoints
Unlike the Times Square image, this image has a lot of areas with very similar colors and little variation. Because of this, JPEG can compress the image better.
On an image that can be compressed better, our 20K budget goes farther. For this image, we only need three image breakpoints to cover the full range of sizes that the image will be used at.
Microsoft Logo — 1 Image Breakpoint
This is a simple PNG8 file. At its largest size (990×660), it is only 13K. Because of this, it fits into our 20K budget without any modifications.
On a recent consulting project with a company that has over 800,000 images on its site, we identified a class of images—some icons, little badges, etc.—where the size of the image on desktop retina was not much different than the size used on mobile either because the image resolution doesn’t vary much or because the image compresses well. For those images, we decided to deliver the same size image to all screen sizes.
Every image is different in the way it compresses
Take a look at the other images on the sample page we created. See how the number of breakpoints vary even through all the images start with the same resolution end points.
This diversity exists despite the fact that with the exception of the Microsoft logo, all of the images start at the same size with the same compression settings. On a real site, we would see even more diversity with varying levels of JPEG quality, PNG8 with gradients going horizontally instead of vertically, and PNG32 images in the mix.
But what intrigues me about this approach to setting breakpoints is that it we wouldn’t be setting one-size-fits-all image breakpoints. Instead, we would make decisions about where the breakpoints should exist based on the our goals for user experience—the performance budget—and the unique characteristics of the image and how will it can be compressed.
What conclusions can we draw from this thought experiment?
The point of this thought experiment wasn’t to provide a complete methodology to set responsive image breakpoints. I started by simply asking the question about whether we might be able to use performance budgets to come up with a way to calculate what are sensible jumps in image sizes.
But the outcome of this exercise has caused me to draw some interesting conclusions as well as sparking more questions about responsive images:
- Images do contain clues that can tell us where the breakpoints should be.
Last year I wrote that “the problem is there is nothing intrinsic to the image that would guide you in deciding where you should switch from one size of the image to another.” But this experiment shows that images do have intrinsic information—how well the image compresses, what type of compression is being used, the range in size between the smallest and largest use of an image—that can be used to decide when you should switch from one source file to another.
- We can set a performance budget for flexible images.
There’s no reason why we can’t treat the use of flexible images like any other feature that we add to a page and define a performance budget for its use. In fact, setting a performance budget for flexible images could be the key to making informed decisions about where image breakpoints should be set.
- Automated image resizing and compression is a must.
I have already written about how automated image services will likely be a must for sites in the future. If a company wanted to use a technique like this to set their breakpoints, they will need an automated way to do it.
- Can we set a performance budget for flexible images across an entire site?
For our sample page, setting the performance budget to 200K for the whole page worked well. But in the real world, we often don’t know how many images are going to be on a given page. Similarly, we may not know what pages a given image is going to be added to. It seems like it would be useful to be able to say that for any given flexible image on the site, we’ve established a 20K budget. It would be less precise than a per page limit, but it may be the only practical way to translate this thought experiment into a production environment.
- An image and its breakpoints could be stored as a bundle.
The outcome of this approach to image breakpoints is that the breakpoints could be specific to the image no matter what context the image is used in. You could store the calculated breakpoints with the image and whenever the image is displayed on a page, no matter what size the image is used at within the page, the same breakpoints could be used.
- An image and breakpoint bundle would be difficult to use with the proposed picture and srcset standards
Image breakpoints calculated this way depend on knowing the size of the element in the page. Both picture and srcset make the switching of image sources contingent on the size of the viewport instead of the element. This means that you’d have to find a way to translate your image breakpoints to viewport sizes which would undermine a lot of the utility of storing breakpoints with the image.
Crazy? Or crazy like a fox?
Phew, you made it to the end. So what do you think? Is there merit in using performance budgets for flexible images to determine responsive image breakpoints?
Thanks to John for creating the sample script and for being my partner in crime on this crazy idea and to Lyza for being an amazing photographer and publishing her photos under creative commons.
I recently had the opportunity to work with a company that is moving to a responsive design and has over 800,000 images on their site. These images come from all over the world. I learned a lot about what it means to tackle images in a responsive design on a large scale.
One of the big lessons is that we spend a lot of time discussing what the frontend solutions for responsive images should be—the new picture element or srcset or a magical new image format—and little time discussing how backend systems and human processes might need to change.
The company I consulted has procedures in place for images. These processes include having the images enhanced if necessary, cropped to fit, resized, and then saved in a web optimized format to fit exactly how the image is used on the page. That process makes a lot of sense for the current fixed width site, but will break down when the site becomes responsive.
These conversations led me to document my ideal scenario. If I could wave a magic wand for organizations, what would I put in place for their responsive images processes and tools?
The result was eight guidelines and one rule for responsive images.
8 Guidelines for Responsive Images
1. Use vector-based images or font icons whenever you can
Wherever possible, avoid the problems of pixel-based images by using vector alternatives.
SVG has decent browser support. The Filament Group has a project called Grunticon that will generate SVG and fallback PNGs along with the CSS necessary for you.
Icon fonts are also a big win with fairly wide support. You can create your own fonts with just the icons you need. A bunch of images can be contained in a single HTTP Request which means icon fonts provide similar performance benefits as CSS sprites used to.
Just make sure you use progressive enhancement for your icon fonts and use them in an accessible manner.
2. Encourage people to upload the highest quality source possible
As prices for high-density screens go down, they are starting to show up in more devices and at larger sizes. It isn’t hard to imagine Apple releasing Retina Cinema Displays in the not so distant future.
Having content authors upload the highest quality image they have into whatever system you use to manage content means that you’ll be ready for whatever resolutions are needed in the future. Managing and keeping track of these assets will make life easier if you redesign the site in the future.
Storing the highest quality source files will likely mean an increase in storage requirements, but storage is cheap these days.
3. Provide an automatic image resizing and compression service
If you have a lot of images on your site, it will no longer make sense to resize them and optimize them for the web by hand.
For example, if the client I was consulting with had decided that they needed three responsive image breakpoints, that would mean three times their current 800,000 images. And that is just standard definition. Multiple the number of images by two if you want to support retina displays. The end result would be 4.8 million images.
Now they wouldn’t have to do all the images at one time, but it still a lot of work. So instead, companies need to build or buy centralized systems that will resize and compress images.
4. Images can be resized to any size with URL parameters
That image resizing service? It should be able to take information that identifies a source image as well as the measurements that the image is needed at and resize the image on the fly.
A good example of a service like this is Sencha SRC. See how you can declare in the URL just the width or the height and the service will resize the image proportionately. That’s what you want.
alt="My constrained image"
If you’re an Akamai customer, the Akamai Edge Image Manipulation service might do the trick for you. It is currently in beta and offers a ton of useful functionality.
Whatever you do, you’ll want to make sure you’re providing smart caching and not breaking external caches.
5. Provide automated output of your image markup
It doesn’t really matter what solution you decide to use in your markup for responsive images. My personal preference is the PictureFill solution, but there are many options to choose from.
But no matter what solution you pick, you should centralize the markup so that it will be easier to change in the future.
For example, in your templates, you might not put any direct HTML, but instead define a series of source images and breakpoints like so:
And then pass that to a central function that would output the correct PictureFill markup or whatever markup you’re going to use.
Don’t get hung up on the syntax or the data contained in the example. The key is that by centralizing image markup in a function, you can change it quickly when the standards evolve.
6. Provide a way to override resized images for art direction needs
For most sites, the most important use of responsive images will be to provide different resolutions of images based on the size that the image is used on the page at a particular viewport size. That is what we call the resolution switching use case.
Occasionally you will find that simply resizing an image isn’t sufficient. A smaller version of the same image becomes unrecognizable.
But at a smaller size, the image can be hard to discern.
If you make changes to the image source at smaller sizes, the image can be easier to see.
This is what we call the art direction use case.
Another place where you may need art direction is for images that contain a combination of text and photography. Ideally, you can separate the photography from the text, but sometimes you can’t get the control you need and when you shrink the image, the text becomes unreadable.
For this recent project, we were able to identify a handful of templates where the need for art direction might be necessary. For those templates, the CMS will be modified to allow authors to upload different sources and define at what breakpoints those sources should be used.
7. Integrate image compression best practices
If you’re going to centralize your image resizing as a service, this is the perfect opportunity to incorporate the best tools in image compression.
Google has some great information on ways to optimize images. It should also go without saying that you need to set far future expires headers for your images.
8. Bonus: Detect support for WebP image format and use it
As long as you’re centralizing image delivery, why not look into supporting WebP?
The average WebP file size is 25% – 34% smaller compared to JPEG file size. WebP compresses 34% better than libpng, and 26% better than pngout for loseless images.
Google wrote recently about how they’re checking for WebP support when an image is requested and automatically serving up the WebP alternative if the browser is capable of displaying that image.
Ideally, browsers would simply support WebP, but in the meantime, there are some performance gains that could be had and it might not add too much to your image resizing service to support it.
The one and only rule for responsive images:
Plan for the fact that whatever you implement will be deprecated
No one knows what the future of responsive images holds. A few years from now, we will probably look back on the hacks we’re using and laugh at our naivety.
The one thing we can be certain about is that we’re going to need to replace what we implement now when standards catch up with responsive images.
So whatever you build, make sure it is flexible and can be changed easily when the ultimate solution for responsive images becomes apparent.
I recently did some research into the HTML that Facebook was using in the old version of its iOS app. More on that in a future post. In the meantime, I thought I’d share how to inspect what an iOS app is sending over the network using Charles Proxy.
Before I begin, I must disclose a few things:
- I am not an expert at using a proxy server nor even at how to use Charles Proxy. I am likely using Charles Proxy in naive ways. I have resisted writing this for some time because I know I am an amateurish hack.
- Charles Proxy runs on Windows, MacOS and Linux. I have only used the Mac version and will be talking about it.
- I am a HUGE fan of Charles Proxy. It gives me tremendous joy to be able to see into activity that I otherwise would have no insight into. I feel like the app gives me super powers. I am unabashedly biased about this product.
Ok, let’s start looking at an app shall we?
Setting up Charles Proxy for iOS
First things first, you have to buy Charles Proxy. You can get a free trial to begin with. But the full price for the app is $50 with discounts if multiple licenses are purchased.
You will be surprised to learn that I think it is well worth the $50 and one of the best purchases I’ve made. ;-)
After you install Charles and have it running, getting your iOS device to recognize Charles is fairly easy. First, make sure your iOS device is on the same network as the machine you’re running Charles on.
Go into your network settings on the iOS device and select the wifi network.
At the bottom of the network settings is the HTTP Proxy settings. They are likely off. Select Manual. Enter the IP address of the machine running Charles for the Server and 8888 for the Port.
If you open Safari (or anything else that makes a network connection), you should receive a prompt in Charles asking if it is ok to let the device connect to your proxy server.
After you approve your device, all future network traffic will be routed through Charles. You can record the traffic by hitting the record button in Charles.
If you see a lot of noise coming from your Mac, turn off the Mac OS X Proxy by unchecking it under the Proxy menu or by pressing Shift-Command-P.
Enabling SSL Proxying
Now you can launch the app you want to inspect and see what it downloads. I’ll use the profile page in the new Facebook app as an example.
When you first load the profile page in Charles proxy, things looked promising. You can see a series of requests, how long they took to download, and their size.
Unfortunately, if you try to see what the server sent in response to the request, or even any details on the request itself, you’ll find that you can’t see much or what you do see will be gibberish.
That’s because Facebook is using SSL to encrypt most of the communication between the app and the server. To see what is going on inside that communication, you need to trick your phone into thinking Charles Proxy’s SSL Certificate is valid for the domains you want to inspect.
Setting this up is a fairly easy two step process.
Step 1: Install the Charles Proxy SSL Certificate on your iOS device
If you’re using iOS 4 or above, visit http://charlesproxy.com/charles.crt on your device and install the certificate for Charles.
If you’re on an older version of iOS, want to use Charles as part of your app development, or want to use it with the simulator, check out Charles Proxy’s iOS SSL documentation.
Step 2: Configure Charles Proxy to support SSL proxies for the domains you need
In the menu under Proxy, select Proxy Settings. Select the SSL tab. Enable SSL Proxying if it isn’t enabled.
You can now add as many domains as you need to complete your task. Wildcards work. For examining the Facebook app, I added the following domains:
Basically, I watched the queries and saw what domains requests came in for that I couldn’t see because they were under SSL, and then I proceeded to add them to the list.
Looking at the requests again
Now that we’ve got SSL proxying in place, let’s take another look at those Facebook requests for the profile page and see if we can see more of what is going on.
Ah… that’s more like it. We can now see the full path requested. If we tap on the response section, we can also see what the content of the response was. In this case, the profile page is still an HTML page even in the new “native” Facebook app.
Now that you have the requests and responses, you can do some really cool stuff. Select all of the relevant requests to look at the total payload delivered.
The overview tab will tell you how many requests were made, how many errors occurred, etc.
The Summary tab will let you know the total size of the assets downloaded and the amount of time it took. You can easily sort the requests to find the largest files or the files that took the most time to download.
Exporting your results
Charles allows you to save your session in a Charles Session file or export it as a HAR (HTTP Archive Specification) file or other common formats like CSV which can be shared with others.
Remember to turn off the HTTP Proxy setting
After you’re done testing, you’ll need to turn off the HTTP Proxy settings on your phone. I know it seems obvious, but there have been multiple times where I’ve thought a site was down or my network wasn’t working only to realize I forgot to turn HTTP Proxy off.
X-ray vision for your little black rectangle with rounded corners
That’s it. Easy huh?
You can use Charles Proxy to examine mobile web sites or any network requests so long as the device you are testing on supports HTTP Proxies. It’s a great tool to have in your mobile toolbox.