Making Responsive Websites Perform

There was a time when you could confidently differentiate between a desktop web page and a mobile web page. So much so, in fact, that an entire industry grew up around repurposing desktop sites for mobile.

For a while, you were no one if you didn’t have a separate mobile site on a separate domain. Then things started to change.

Mobile displays improved beyond all recognition. So did mobile browsers. Tablets threw another element into the equation. 4G came along. Retina displays offered new levels of clarity for end users.

Suddenly, the line between desktop and mobile was looking blurry.

At the same time, there was growing diversity in the size and resolution of desktop displays.

And a growing headache for web designers.

Gone were the days when you only had to cater for a handful of viewport sizes. Things were getting complicated.

Fortunately, help was at hand in the shape of media queries and the concept of responsive design.

Thanks to media queries, it became possible to vary styles and layout – even content – depending on the user’s viewport width and screen resolution. Of course, media queries are by no means the only tool in the responsive designer’s bag of tricks, but it’s fair to say that they form the basis of the technique.

This was great news for mobile. Responsive design meant that you could effectively deliver different versions of the same site to different devices. All without developing a separate mobile site on a different domain.

What About Performance?

Site owners are starting to realise that end users care about performance. Retailers in particular are beginning to appreciate that shaving milliseconds off load time can translate to millions on the balance sheet.

Fortunately, responsive sites offer one clear performance benefit over their dedicated mobile cousins: the redirect to a mobile domain is eliminated.

However, despite this, responsive design has managed to acquire a bit of a reputation for poor performance.

In some ways, this is rather unfair, but it’s worth looking at the extra performance challenges that responsive design springs on the unwary…

Images

Image files are big. And because they’re big, they’re often to blame for slow load times. They’re therefore a good place to start for anyone trying to optimise a site’s performance.

Unfortunately, one of the first solutions to delivering images responsively wasn’t great for performance.

The technique is beautifully simple. Just use max-width: 100% to make sure images scale to the width of the containing element:

img
{
max-width: 100%; 
}

As the container shrinks to suit smaller viewports, any images inside will shrink with it. Easy!

But there’s a problem. The size of the image might shrink on the screen, but the size of the file remains the same. This is far from ideal from a performance point of view. You could be sending an 800 x 800 pixel image down the wire, only for it to be displayed at 80 x 80 pixels: in other words, you could be transmitting hundreds (or thousands) of unnecessary bytes. Not only will the image take a long time to load, all those redundant bytes could be depleting the end user’s valuable data allowance.

However, this is not the only – nor even the best – way to deliver responsive images. For one thing, an image that works at 800 pixels wide won’t necessarily work quite as well at various fractions of that size.

To deal with this, you can use a media query to display different versions of the image depending on viewport size by using a media query and display: none.

CSS:

@media (min-width: 601px) {
#croppedImage
{
display:none; 
}
}
@media (max-width: 600px) {
#largeImage
{
display:none; 
}
}

HTML:

<img id="largeImage" width="400" height="400" alt="" src="images/largeImage.jpg">
<img id="croppedImage" width="200" height="200" alt="" src="images/croppedImage.jpg">

This allows you to display different versions of an image, rather than just the same image at different sizes. However, it doesn’t cut the number of bytes. In fact, the overall page size will be larger, since all the images will be loaded, whether they’re displayed or not.

A better alternative – if it’s practical – is to use background images in <divs> instead of <img> elements. This is preferable because images referenced in CSS are loaded only if they’re used (as long as they’re not data URIs):

@media (min-width: 601px) {
#largeImage
{
width:400px;
height:400px;
background-image:url(/images/largeImage.jpg);
}
#croppedImage
{
display:none;
}
}

@media (max-width: 600px) {
#croppedImage
{
width:200px;
height:200px;
background-image:url(/images/croppedImage.jpg);
}
#largeImage
{
display:none;
}
}

This works well: visitors download only the images they need, as and when they need them. The problem is that it’s untidy, effectively treating content as style. As such, it potentially creates a maintainability problem and could also result in important images being ignored by search engines.

Instead, why not use SVG (scalable vector graphics): an image format that scales by its very nature? SVG images also have the advantage that they are easily styled with CSS (see this great tutorial on making SVGs responsive with CSS). This is perfect for icons and logos, but unfortunately, you won’t be able to use SVGs for photos – for these you’ll have to resort to raster formats, such as JPEG.

Another option is to use one of a number of JavaScript solutions to deliver responsive images. This is a popular way to do it, but it adds another layer of complexity. What’s more, since JavaScript blocks DOM construction, any solution involving JavaScript has the potential to hold up rendering. So while there are some very clever plugins out there, just by introducing JavaScript into the equation, you are, to some degree, resigning yourself to the lesser of two evils.

Until recently, these were the only options.

Now, however, the <picture> and <source> elements, and the srcset and sizes attributes, are finally bringing truly responsive images to the web. The new specification is also starting to gain browser support, with full support in Chrome and Opera, and support for resolution switching in Safari. Until other browsers catch up, there’s an excellent JavaScript polyfill.

In this brave new world, you can use srcset to set out a list of candidate images for the browser to pick from. You can then use a media query in the sizes attribute to dictate the size at which the image will be displayed. Using the <picture> element together with media queries inside one or moreelements, you’re able to specify a different range of images for different conditions (e.g. for viewports up to a certain width, use image a, b or c, and for larger viewports use image x, y or z). This is useful if you need to deliver a cropped version of an image for users with small screens.

The precise detail of how to use the new syntax is outside the scope of this article, but you can find an excellent tutorial at alistapart.

Perhaps the only disadvantage of this new specification is that it’s quite long-winded, which could mean bloated HTML on pages with lots of images. However, the benefits far outweigh the drawbacks.

Loading CSS You Don’t (necessarily) Need

Although media queries allow you to apply different CSS rules depending on the criteria you’ve set, there’s no getting away from the fact that end users will have to download all the CSS that might apply. This is true even if you put your CSS in separate files and place your media query in the <link> element.

For example, both the following style sheets will be loaded, regardless of viewport width:

<link rel="stylesheet" media="(max-width: 600px)" href="css/style1.css">
<link rel="stylesheet" media="(min-width: 601px)" href="css/style2.css">

This isn’t a browser bug. The criteria used in media queries often relate to things that change during a visit to a page. For example, a visitor may decide to resize the browser window or rotate their tablet/mobile device. The resulting change in display should be seamless, and firing off a request for another CSS file would be far from ideal. This is especially true for mobile devices, which look to close radio links at the earliest opportunity in order to preserve battery power. Potentially having to re-establish that link when the viewport size changes could be bad news for battery life.

However, Chrome makes the effort to deal with these different files in an intelligent way. While all the files will be downloaded, only the one with the currently matching media query will block rendering. Any others will load with lower priority.

Unfortunately, other browsers aren’t quite as obliging. In Firefox, for example, unused CSS files don’t just block rendering – they also block the loading of other objects on the page.

The waterfall chart below illustrates the point. The images on this page don’t start loading until the unused CSS file has downloaded completely:

Download of Unused CSS file

You can get around this by using JavaScript to load CSS conditionally but, as we’ve already seen, JavaScript comes with its own performance costs.

What Does All This Mean for The Performance of a Responsive Site versus A Mobile Site?

Well, mobile users and desktop users on a responsive site will have to download the same CSS.

And there’s going to be more of it than there would be on a site designed just for desktop or mobile.

What’s more, a dedicated mobile site is more likely to use a lighter, stripped down version of the desktop CSS (although this is perhaps less true now, as users grow to expect a richer experience on ever more sophisticated mobile displays).

So other things being equal, it looks as though there’s something in the argument that a responsive is likely to be slower than a mobile site because of the extra CSS required. However, as long as designers are aware of the potential pitfalls, they should be able to create fast-loading style sheets for a responsive site. In particular, it’s a good idea to:

  • avoid using data URIs for images – binary background images will (normally) be loaded only if/when they’re needed, but all data URIs will be loaded regardless.
  • keep it light – since all CSS has to be downloaded, it’s important to be efficient. This means avoiding duplication and making sure that global rules are set outside the media query driven CSS.
RESS (Responsive Web Design + Server Side Components)

RESS is a hybrid between responsive and adaptive design, which involves user-agent sniffing on the server to look at the characteristics of the client device and deliver content appropriate to it.

If one of the objections to responsive design is that it involves delivering all content to all devices, why not mitigate this by cutting out some of that content where you can?

This can make a lot of sense. If there’s an image you know you’ll never want to display on devices whose screen is below a certain size, you might as well not send it to those devices, saving bandwidth and cutting load time.

What’s more, if you’re using media queries that you know couldn’t possibly be satisfied on certain devices, there’s at least an argument for separating your CSS into different files and loading them conditionally.

It’s worth bearing in mind that this whole process isn’t ‘free’ in performance terms. Some work obviously has to be carried out on the server, which takes time – probably not enough to outweigh the benefits, but it’s something to be aware of.

The verdict

Are responsive sites slow?

It depends what you mean by slow.

Is the fastest responsive site you could make likely to be slower than the fastest dedicated mobile site you could make?

Probably.

We’ve also seen that there are a few pitfalls. If you’re not careful, it’s easy to end up forcing users to download a lot of redundant images and CSS, making your responsive site much slower than it needs to be.

However, it doesn’t have to be that way. It’s perfectly possible to create a responsive site that’s every bit as fast as it needs to be and delivers an excellent user experience. And as both standards and browsers start to catch up with what developers want to deliver, it should start to get easier.

Like it? Share it.

Leave a Comment Yourself

Your email address will not be published. Required fields are marked *