Images are a great way to polish up a page and make a better impression on your visitor. But, if not used correctly, images can also have a detrimental effect on the performance of your page. Compared to text, an image is often relatively large. As such, suboptimal images have a major effect on page speed.
This guide explains how you can use images on your page without hurting your page speed.
Photos shot with your phone or camera often have high resolutions. A photo from an iPhone is 3264 x 2448 pixels. Higher dimensions result in a larger file, and that results in longer load times.
Worst of all: it's often unnecessary. If that photo with an original size of 3000 x 2000 pixels is displayed as a 300 x 200 image on your site, you're wasting your visitor's bandwidth, causing unneeded loading times.
If this is the case on your site, Google Pagespeed Insights will show the suggestion to Properly size images. It calculates the size of the image against how big it's rendered on the page, and if the loaded image is a lot bigger than the area it gets on the page, that results in a warning.
The fix is relatively easy: change the dimensions of your image to the size it is shown on the page. In the above example, you would reduce it to 300 x 200 pixels, save about 90% bandwidth, without losing any image quality.
The above example sounds easy, but given the variety of screen sizes, reality can be a bit more complex. On a desktop screen, you may want to show the image at 600 x 400 pixels, while on a mobile phone, 300 x 200 pixels makes more sense.
Responsive images allow you to serve images depending on the screen size of your visitor. Here's how that works:
You resize the image to three different formats:
- a mobile version of 300 x 200 pixels, called photo-large.jpeg
- a version for tablets of 450 x 300 pixels, called photo-medium.jpeg
- a desktop version of 600 x 400 pixels. called photo-small.jpeg
Next, you use the following code on your page to serve the image depending on the screen size of your visitor:
<source srcset="/img/photo-large.png" media="(min-width: 1200px)">
<source srcset="/img/photo-medium.png" media="(min-width: 360px)">
<source srcset="/img/photo-small.png" media="(max-width: 360px)">
<img src="/photo-large.jpeg" alt="A photo">
Let me explain: the picture element contains all photos for the different screen sizes (sources), as well as an IMG tag, which serves as a default. The code above will render a small photo on screens under 360 pixels width, a medium photo for screens between 360 and 1200 pixels, and a large photo on screens over 1200 pixels. Smaller screens will display smaller images, resulting in better page performance.
After making sure the image has appropriate dimensions, we need to look at encoding. The most commonly used format for photos is JPEG. This comes with a compression level between 0 and 100. Compression is about reducing the image size, while also reducing the quality of the image. Most photo editing tools will let you set the compression level when saving the image. Setting compression to 100 will result in a super-sharp, very large file, unsuitable for the web. Setting it to something below 10 will result in a very small file that looks nothing like the original.
Finding a balance, you'll end up at around 85% compression. This results in hardly any quality loss (at least not something anyone would notice), while significantly reducing the file size.
If your images are saved with a higher than 85% compression level, Google Pagespeed Insights will likely suggest you Efficiently encode images: reducing the quality slightly, and seriously bringing down the file size.
Tools like Kraken.io help you further compress images, with or without quality loss.
We've discussed caching policies in a separate chapter, but it's good to highlight it's importance for images. Caching is about storing assets (like images) on the visitor's computer, so they won't have to be downloaded on a subsequent page view or visit. That saves a lot of loading time.
If you haven't set a caching policy, the browser will reload the image on every pageview, which is especially wasteful if the image is shown across multiple pages. Google Pagespeed Insights will then show a suggestion to Serve static assets with an efficient cache policy. Fixing this will speed up your website, and it's relatively easy. This code will allow all images to be cached for 3 months:
ExpiresByType image/jpeg "access plus 3 month"
ExpiresByType image/gif "access plus 3 month"
ExpiresByType image/png "access plus 3 month"
ExpiresByType image/webp "access plus 3 month"
ExpiresByType image/svg+xml "access plus 3 month"
ExpiresByType image/x-icon "access plus 3 month"
There are various image file types: JPEG, GIF, PNG, SVG, and WEBP are common. How do you decide which one to use?
All formats are very different, and which one to use depends on the image. The common ones and their pros and cons are:
JPEG allows for good compression, resulting in efficiently sized images. However, it cannot have transparency, and you can't use it for animations.
PNG allows for lossless compression, which means you don't lose any quality when compressing the file. PNGs also allow transparency. Use PNG for screenshots and graphics. PNG can't be animated.
GIF is relatively inefficient but allows for animation and transparency. Due to its inefficiency, the only real use case is animated GIFs. Even then, you might want to consider video instead of GIFs, as that's much more efficient.
SVG is very different from the other formats, as it's more code-based. Icons and simple logos in SVG can be extremely efficient, but SVG is not suited for complex images.
WEBP is a new format that has great compression, allows for transparency, and can be animated. The big downside is that not all browsers support it. So even though Google Pagespeed Insights may encourage you to use WEBP, we're a bit more conservative: at this point, its support is insufficient to use WEBP. That may change soon though.
So when Google tells you to Serve images in next-gen formats, take that with a grain of salt.
Say you have a large page, with lots of images shown below the fold: not directly visible on the visitor's screen, but only after scrolling. Wouldn't it be great if those would only be loaded only if the visitor scrolls down to those images?
Or, as Pagespeed Insights puts it: Defer offscreen images
That's called lazy-loading: not loading the images until it's needed. This reduced the number of images that need to be loaded. Especially for pages with a lot of images, this can lead to much better performance.
The loading attribute can have 3 values:
- lazy: don't load the image until it's almost in the viewport
- eager: load it as fast as possible, regardless of where it sits on the page
- auto: do nothing special. A pretty useless value that you shouldn't use.
Add the loading="lazy" attribute to images that aren't directly visible when loading the page, and you'll see a big performance improvement.