How to Reduce Website HTTP Requests for Images

Images are an important part of any website. So important that we tend to use a lot of them. And then our websites become too slow. Using the right image formats and sizes is very important, and I suggest you read The picture tag and How to get 100 website performance score.

Here we look at different tricks that can improve the performance of a website by reducing the number of HTTP requests for images but still using all the images.

Let’s assume there is a website that uses 100 different images, so it makes 100 HTTP requests to load them. What if instead of doing 100 HTTP requests we could reduce that number to maybe 10 or 20. Even 50 is twice as better right?

Good candidates for this are the social media icons, country flags, various menu / arrow icons, or button images with variations for mouseover, focus and active states.

Svg Use

For logos and icons, SVG images are perfect. They scale right and their colors can be changed with CSS so no need for extra image variations.

Now instead of loading a bunch of SVGs, we can load a single SVG with multiple icons in it.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 40 40" display="none" width="0" height="0">
  <symbol id="icon-1" viewBox="0 0 40 40">
    <path d="M34.9,30.5V15.6c-0.4,0.4-0.8,0.9-1.4,1.2c-3.4,2.7-6.2,4.8-8.2,6.6c-0.6,0.5-1.1,0.9-1.6,1.2c-0.4,0.3-0.9,0.6-1.7,0.9 c-0.7,0.3-1.4,0.5-2,0.5l0,0c-0.6,0-1.2-0.2-2-0.5c-0.7-0.3-1.2-0.6-1.7-0.9c-0.4-0.3-0.9-0.7-1.6-1.2c-2.1-1.7-4.8-3.8-8.2-6.6 c-0.5-0.4-0.9-0.8-1.4-1.2v14.9c0,0.2,0.1,0.3,0.2,0.4C5.7,31,5.9,31.1,6,31.1h28.4c0.2,0,0.3-0.1,0.4-0.2 C34.8,30.8,34.9,30.7,34.9,30.5L34.9,30.5z M34.9,10.2V9.7c0,0,0-0.1,0-0.2c0-0.1,0-0.2-0.1-0.2c-0.1,0-0.1,0-0.1-0.2 c0-0.1-0.1-0.2-0.2-0.1c-0.1,0-0.2,0-0.3,0H5.8C5.6,8.9,5.4,9,5.3,9.1C5.2,9.2,5.1,9.3,5.1,9.5c0,2.2,0.9,4,2.8,5.5 c2.5,2,5.1,4,7.7,6.1c0.1,0.1,0.3,0.2,0.7,0.5c0.4,0.3,0.6,0.5,0.9,0.7c0.2,0.2,0.5,0.4,0.8,0.6c0.3,0.2,0.7,0.4,0.9,0.5 c0.3,0.1,0.6,0.2,0.8,0.2l0,0c0.2,0,0.5-0.1,0.8-0.2c0.3-0.1,0.6-0.3,0.9-0.5c0.3-0.2,0.6-0.4,0.8-0.6c0.2-0.2,0.5-0.4,0.9-0.7 c0.4-0.3,0.6-0.5,0.6-0.5c2.7-2.1,5.3-4.2,7.7-6.1c0.7-0.5,1.4-1.2,2-2.2C34.6,11.8,34.9,11,34.9,10.2L34.9,10.2z M37.3,9.5v21 c0,0.8-0.3,1.6-0.9,2.2s-1.4,0.9-2.2,0.9H5.8c-0.8,0-1.6-0.3-2.2-0.9c-0.6-0.6-0.9-1.4-0.9-2.2v-21c0-0.8,0.3-1.6,0.9-2.2 s1.4-0.9,2.2-0.9h28.4c0.8,0,1.6,0.3,2.2,0.9S37.3,8.7,37.3,9.5z"></path>
  </symbol>
  <symbol id="icon-2" viewBox="0 0 40 40">
    <path d="M7.9,24.9l10.8,7.2v-6.4l-6-4L7.9,24.9z M6.8,22.3l3.4-2.3l-3.4-2.3V22.3L6.8,22.3z M21.4,32.1l10.8-7.2l-4.8-3.2l-6,4 C21.4,25.6,21.4,32.1,21.4,32.1z M20,23.3l4.9-3.3L20,16.8L15.1,20L20,23.3z M12.7,18.3l6-4V7.9L7.9,15.1L12.7,18.3z M29.8,20 l3.4,2.3v-4.6L29.8,20z M27.3,18.3l4.8-3.2L21.4,7.9v6.4L27.3,18.3z M36,15.1v9.8c0,0.5-0.2,0.9-0.6,1.1l-14.6,9.7 C20.5,35.9,20.3,36,20,36c-0.3,0-0.5-0.1-0.8-0.2L4.6,26C4.2,25.7,4,25.4,4,24.9v-9.8c0-0.5,0.2-0.9,0.6-1.1l14.6-9.8 C19.5,4.1,19.7,4,20,4c0.3,0,0.5,0.1,0.8,0.2L35.4,14C35.8,14.3,36,14.6,36,15.1z"></path>
  </symbol>
</svg>        

Then with use tag we can get an individual icon:

<svg>
    <use xlink:href="#icon-1"></use>
</svg>

<svg>
    <use xlink:href="#icon-2"></use>
</svg>

Now all your social media icons are in one file. If you embed the SVG inside the HTML there is no image left to load.

Css Sprites

Icon sprite We have a 924x252px image. There are 11 rows and 3 columns. This means that each image has a width of 924/11=84px and a height of 252/3=84px.

To show one of the icons from the image we need to:

  • Set the size of the element to 84x84px, the size of one of the icons inside
  • Move the background to show the position of one icon

The position of a background’s pixel increases from left to right (starting from 0 to 924) and from top to down(from 0 to 252). By default, we are on position 0x0 so we see the first icon. To display a different icon we need to move the background to the left and down.

In CSS we load the image and set it as background:

.social-icons {
    background-image: url('./icon-sprite.jpg');
    background-repeat: no-repeat;
    height: 84px;
    width: 84px;
}

.fb-transparent {
    background-position: 0 0;
}
.twitter-transparent {
    background-position: -672px 0;  /* 672 = 8*84  */
}
.twitter-color {
    background-position: -672px -84px; 
}
.twitter-black-and-white {
    background-position: -672px -168px; /* 672 = 8*84, 168 = 2*84  */
}

In HTML we use the CSS classes:

<button class="social-icons fb-transparent"></button>

<button class="social-icons twitter-transparent"></button>

<button class="social-icons twitter-color"></button>

<button class="social-icons twitter-black-and-white"></button>

Data Uri

You can go further and encode the image content encoded as a Base64 string (using a tool like ezgif.com). This way the image content is embedded in the HTML so there is no need to load it separately. Note that this method should be used only for small images!

The only difference from above is the way the image is set as background:

.social-icons {
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA5wAAAD8CAYAAA....);
    background-repeat: no-repeat;
    height: 84px;
    width: 84px;
}

Img Tag with Object-Fit and Object-Position

Instead of setting the image as background using CSS, we can use the img element. By using the object-fit and object-position CSS properties we can make the img show only a piece of the entire image, just like we did with the CSS sprites.

.social-img{
    height: 84px;
    width: 84px;
    object-fit: none; /* REQUIRED */
    object-position: 0 0;
}

.social-img-twitter-transparent{
    object-position: -672px 0; /* Move the content to a specific place */
}

In HTML we set the image source and use the CSS classes:

<img class="social-img" src="./icon-sprite.jpg" alt="Facebook" />

<img class="social-img social-img-twitter-transparent" src="./icon-sprite.jpg" alt="Twitter"/>

Icon Fonts

There are some fonts that instead of rendering letters render icons. To use the icon font you need to first load it as any other font. But then you need to set some special CSS classes and/or letters to show the icon.

Here is for example how to use Material Icons

<!DOCTYPE html>
<html lang="en">
<head>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>

  <span class="material-icons">face</span>

  <span class="material-icons">settings</span>

</body>
<html>

If you want to use icon fonts please check the size of the font file. If you need only a couple of them try to use an SVG instead, it will be much much smaller.

Create the Icons with Css

With a little imagination, one can create even complex shapes in CSS. Here is a great example of what is possible: The Shapes of CSS

Conclusion

There are several ways to reduce the number of HTTP requests made for images by combining multiple images in one:

  1. SVG use
  2. CSS sprites
  3. Img tag with object-fit and object-position
  4. Icon fonts

Use any of the above to make your website a bit faster.