In web performance we’re often interested in preventing big image files from holding up the delivery and display of important content (with lazy-loading, for example).
But let’s not lose sight of the fact that images can be important content too.
What if you don’t want to defer your image, but instead display it at the earliest possible opportunity?
Figure 1 – A rather basic sample page
Retailers, for example, quite often use images to deliver important information about products and offers in home page banners or carousels. Dark background images are also sometimes used to supply the contrast for light-coloured text.
So what’s the best way to get important images to load early?
We built a rather basic test page for a (fictional) furniture retailer. It features a large hero image, overlaid with some white-out offer text, which takes up a fair proportion of the screen. There are also a number of other product images further down the page, all loaded in <img> tags (images courtesy of freeimages.co.uk).
We then looked at different ways to deliver the hero image.
Loading it via the CSS
Since the image is overlaid with text, perhaps the most the natural course of action is to treat it as a background image, loaded via an external CSS file:
However, this can mean that, despite the fact that it’s arguably the most important element on the page, it’s the one of the last objects to load and be displayed:
Figure 2 – Background image loaded via the CSS – render start at 1.2 seconds (tested with WebpageTest, using Firefox at 5Mbps)
Chrome, Firefox and Internet Explorer consistently started loading the background image behind some or all of the images in the HTML.
The pattern was much the same whether we loaded the image via an external CSS file or inline, using a style attribute.
In the normal course of events, this wouldn’t be a massive problem – background images don’t tend to be critical to the page. In this example, however, the user is left staring at a (virtually) blank screen for too long.
Could we improve matters by Base64 encoding the image and embedding it in the CSS?
This approach meant the background image would start to load ahead of other images on the page. It would also eliminate a round-trip.
However, when we tested this in Chrome, it didn’t make for a great user experience. Since CSS blocks rendering, and the background image is quite big, we lost the progressive rendering that we saw in the first test. Instead, virtually all the content was displayed at once.
What’s more, render start was delayed some way beyond the point at which the CSS finished loading. It looks as though this delay might have been due to high CPU utilisation while the browser worked out what to do with the (rather large) data URI:
Figure 3 – Background image as a data URI (tested with WebpageTest, using Chrome at 5Mbps)
Things were even worse in Firefox, where the CSS blocked not just rendering of the page but also the loading of subsequent files:
Figure 4 – CSS blocked subsequent objects in Firefox (tested with WebpageTest at 5Mbps)
Using an <img> element
The other alternative is to treat the background image as content.
This time, we loaded the background image not in the CSS but in an <img> element:
<img src=”css/sofa1Y2.jpg” alt=”” />
<span class=”imagetext”>50% off this classic until July!</span>
We then effectively styled it as a background image in the CSS so we could overlay the text:
margin: 10px 5px 10px 0px;
Since the image no longer depended on the CSS, the browser could start loading it before the style sheet had finished loading. What’s more, images in the HTML tend to get priority over images in the CSS.
Figure 5 – The “background image” loads early, without having to wait for the CSS (tested with WebpageTest, using Chrome at 5Mbps)
We don’t quite get all of these benefits in Firefox because, as we saw earlier, CSS blocks the loading of subsequent objects. However, Firefox still loads and displays the background image ahead of (or at the same time as) the other images on the page:
Figure 6 – The benefits of using an <img> tag in Firefox (tested with WebpageTest at 5Mbps)
Contrast this to the first Firefox test (see Figure 2), where the CSS background image loaded behind the other images.
Browsers give lower priority to background images because they treat content as more important than style. However, browsers don’t really know that much about your site. They don’t know what matters to the people who visit it. And sometimes, you’ll want users to see one of your background images ahead of other content.
The point is that while image optimisation is important, it’s not the whole story – the way images are delivered also matters. And if you need an image to be one of the first things to appear on the page, an <img> element is probably the way to do it, even if your first instinct is to treat it as a background image.