Optimize CSS background images with media queries

Demián Renzulli
Demián Renzulli

Many sites request heavy resources, like images, that are not optimized for certain screens, and send large CSS files containing styles that some devices will never use. Using media queries is a popular technique for delivering tailored stylesheets and assets to different screens to reduce the amount of data transferred to users and improve page load performance. This guide shows you how to use media queries to send images that are only as large as they need to be, a technique commonly known as responsive images.

This guide assumes that you're familiar with Chrome DevTools. You can use another browser's DevTools instead if you prefer. You'll just need to map the Chrome DevTools screenshots in this guide back to the relevant features in your browser of choice.

Understand responsive background images

First, analyze the network traffic of the unoptimized demo:

  1. Open the unoptimized demo in a new Chrome tab.
  2. Press `Control+Shift+J` (or `Command+Option+J` on Mac) to open DevTools.
  3. Click the Network tab.
  4. Reload the page.

You'll see that the only image that's being requested is background-desktop.jpg, which has a size of 1006KB:

DevTools network trace for the unoptimized background image.

Resize the browser window and notice that the Network Log isn't showing any new requests being made by the page. This means that the same image background is being used for all screen sizes.

You can see the styles that control the background image in style.css:

body {
  background-position: center center;
  background-attachment: fixed;
  background-repeat: no-repeat; background-size: cover;
  background-image: url(images/background-desktop.jpg);
}

Here's the meaning of each of the properties used:

  • background-position: center center: Center the image vertically and horizontally.
  • background-repeat: no-repeat: Show the image only once.
  • background-attachment: fixed: Avoid making the background image scroll.
  • background-size: cover: Resize the image to cover the entire container.
  • background-image: url(images/background-desktop.jpg): The URL of the image.

When combined, these styles tell the browser to adapt the background image to different screen heights and widths. This is the first step towards achieving a responsive background.

Using a single background image for all screen sizes has some limitations:

  • The same amount of bytes are sent, regardless of the screen size, even when, for some devices, like phones, a smaller and more lightweight image background would look just as good. In general, you want to send the smallest possible image that still looks good on the user's screen to improve performance and save user data.
  • In smaller devices the image will be stretched or cut to cover the entire screen, potentially hiding relevant parts of the background to users.

In the next section, you'll learn how to apply an optimization to load different background images, according to the user's device.

Use media queries

Using media queries is a common technique to declare stylesheets that will only apply to certain media or device types. They are implemented by using @media rules, which let you define a set of breakpoints, where specific styles are defined. When the conditions defined by the @media rule are met (for example, a certain screen width), the group of styles defined inside the breakpoint will be applied.

The following steps can be used to apply media queries to the site so that different images are used, depending on the maximum width of the device requesting the page.

  • In style.css remove the line that contains the background image URL:
body {
  background-position: center center;
  background-attachment: fixed;
  background-repeat: no-repeat; background-size: cover;
  background-image: url(images/background-desktop.jpg);
}
  • Next, create a breakpoint for each screen width, based on the common dimensions in pixels that mobile, tablet, and desktop screens usually have:

For mobile:

@media (max-width: 480px) {
    body {
        background-image: url(images/background-mobile.jpg);
    }
}

For tablets:

@media (min-width: 481px) and (max-width: 1024px) {
    body {
        background-image: url(images/background-tablet.jpg);
    }
}

For desktop devices:

@media (min-width: 1025px) {
    body {
        background-image: url(images/background-desktop.jpg);
   }
}

Open the optimized version of style.css in your browser to see the changes made.

Measure for different devices

Next visualize the resulting site in different screen sizes and in simulated mobile devices:

  1. Open the optimized site in a new Chrome tab.
  2. Make your viewport narrow (less than 480px).
  3. Press `Control+Shift+J` (or `Command+Option+J` on Mac) to open DevTools.
  4. Click the Network tab.
  5. Reload the page. Notice how the background-mobile.jpg image was requested.
  6. Make your viewport wider. Once it's wider than 480px notice how background-tablet.jpg is requested. Once it's wider than 1025px notice how background-desktop.jpg is requested.

When the width of the browser screen is changed, new images are requested.

In particular when the width is below the value defined in the mobile breakpoint (480px), you see the following Network Log:

DevTools network trace for the optimized background image.

The size of the new mobile background is 67% smaller than the desktop one.

Effects on Largest Contentful Paint (LCP)

Elements with CSS background images are considered a candidate for Largest Contentful Paint (LCP), however, CSS background images are not discoverable by the browser preload scanner, which means you could be delaying your site's LCP if you're not careful.

The first option you should consider is whether your LCP candidate image could work in an <img> element with srcset and sizes attributes for responsiveness. The browser preload scanner will discover <img> elements, and send requests for them while the parser is blocked on rendering.

If you can't (or don't want to) avoid using a CSS background image, the second option would be to preload responsive images to ensure you preload the right image for the proper viewport size. The <link> elements media, imagesrcset, and imagesizes attributes hint to the browser that a given resource hint only applies in certain viewport conditions, avoiding multiple wasted preloads when you only want to load the one resource that's a fit for the current viewport.

Summary

In this guide you've learned to apply media queries to request background images tailored to specific screen sizes and save bytes when accessing the site on smaller devices, like mobile phones. You used the @media rule to implement a responsive background. This technique is widely supported by all browsers. A new CSS feature: image-set(), can be used for the same purpose with fewer lines of code. At the time of this writing, this feature is not supported in all browsers, but you might want to keep an eye on how adoption evolves, as it can represent an interesting alternative to this technique.