Slow loading images impacts not only the user experience but also hurts your site's ranking in the search results. Find out how to improve loading images.
If your website uses quite a lot of images then this may impact the page loading speed as well as the page rendering.
A faster loading website means:
- Better user experience.
- Improving rankings on search engines since site speed is a ranking factor.
- Potentially reducing the hosting cost, if you pay-as-you-go for the transfer data.
Let’s then explore the possibilities of image speed loading.
Optimize your images
This step should be fairly easy. Use the tool to optimize your images. One of the tools could be ImageOptim (Mac only) or pngquant or Squoosh. These tools will help you to optimize your images.
Note: while this type of optimization is usually safe, there are situations where size might be stored in the database and just overwriting the image (e.g. by uploading them directly through FTP) with a newly optimized version may bring an unexpected behavior.
Responsive images with srcset
and sizes
Loading the same image for all viewport sizes impacts not only the loading speed but also the rendering. A single image that perfectly fits into large viewports doesn’t fit well into small viewports (e.g. mobile). If someone uses a small screen device on a low bandwidth network, they’ll download unnecessarily large images.
The srcset
attribute and sizes
can be used to inform the browser about different sizes of the same picture that you have created. Here is an example:
<img srcset="flower-480w.jpg 480w, flower-800w.jpg 800w" sizes="(max-width: 600px) 480px, 800px" src="flower-800w.jpg" alt="Beautiful rose flower"/>
The list of images we’ll give the browser to choose from and the sizes of each image are specified by the srcset
attribute. A comma separates each set of image data from the one before it.
When specific media circumstances are met, sizes
define a set of media conditions (such as screen widths) and suggest the appropriate image size to use.
Lazy loading images
Use the loading
attribute to specify the urgency with which you want an image to load for the browser. Using loading="lazy"
tells the browser to load the image only when it’s just about to be rendered in the viewport. In other words, images that aren’t displayed for the user won’t be fetched by the browser. Example:
<img src="example.png" alt="A description of the image." width="500" height="250" loading="lazy"/>
Benefits of lazy loading
- Reduces initial load time – images that aren’t visible won’t be loaded therefore the page will load faster.
- Saving bandwidth – images that aren’t visible won’t be downloaded therefore bandwidth won’t be used, specifically on limited data plans. In some cases, it may impact the bill you pay for CDN or hosting.
- Improving page rendering – the browser won’t need to process images until they are requested by scrolling the page. That saves processing time, battery, and other system resources.
- Good for SEO – speed loading is one of the most important factors that impacts the search ranking.
Preload the image
You can instruct the browser to preload crucial images in the document’s <head>
.
<link rel="preload" href="example.png" as="image"/>
Note that the browser will have to lower the priority of another resource, like a script
or font file, when you ask it to prioritize downloading one resource, like an image. Preload an image only if it is absolutely necessary. Despite the fact that the word load
appears in the name, the script is not loaded or executed. Rather, it is just scheduled to be downloaded and cached with a higher priority.
Priority Hints – fetchpriority
(experimental technology)
The fetchPriority
property is a hint given to the browser on how it should prioritize the fetch of the image relative to other images. The fetchpriority
property is a hint rather than a directive. The browser will make an effort to honor the developer’s choice. It is also possible that the browser will apply its preferences for resource priority as deemed necessary in case of conflicts.
Note that preload image is mandatory for the browser, while fetchpriority
is a hint that might be used, but not always.
<link rel="preload" fetchpriority="high" href="example.png" as="image"/>
Use browser cache
You may instruct the browser to keep the image in the browser’s cache for a certain time. So, once it’s downloaded the browser won’t download it again until the specified expiration time passes. The most popular is to set cache expiration to 1 year. An example of Apache configuration is through the .htaccess
:
<IfModule mod_expires.c>
ExpiresActive on
ExpiresDefault
ExpiresByType image/bmp "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
</IfModule>
<IfModule mod_headers.c>
# 1 Year
<FilesMatch "\.(ico|pdf|flv|jpe?g|png|webp|gif|swf|svg)$">
Header set Cache-Control "max-age=29030400, public"
Header unset ETag
FileETag None
</FilesMatch>
</IfModule>
Use image-set()
for the background images
For high pixel density screens, the image-set()
CSS functional notation allows the browser to select the best CSS image from a list of options.
The CSS specification says:
Delivering the most appropriate image resolution for a user’s device can be a difficult task. Ideally, images should be in the same resolution as the device they’re being viewed in, which can vary between users. However, other factors can factor into the decision of which image to send; for example, if the user is on a slow mobile connection, they may prefer to receive lower-res images rather than waiting for a large proper-res image to load. The image-set() function allows an author to ignore most of these issues, simply providing multiple resolutions of an image and letting the UA decide which is most appropriate in a given situation.
Example:
.example-background { /* Fallback */ background-image: url("example.png"); /* Standard; should be transformed to prefixed versions using Sass or Less */ background-image: image-set("example.png" 1x, "example-2x.png" 2x); }
Displays with lower resolutions will experience better performance because their browser will automatically request the lower resolution image, which automatically will improve the speed loading because the image will be smaller.
Use a CDN – content delivery network
By storing the files for your website at numerous data centers across the world you will serve the assets with the closest server to the user. In other words, when someone visits your website, they can then download your files from the nearest global data center.
Extra tip:
Inline svg element replaced with image element
There are cases where we render a lot of <svg>
-s (e.g. icons) and at the same time some of them are invisible for the user. This causes not only the loading of too many resources but also impacts the rendering performance.
To fix the issue replace embedded <svg>
elements with <img src="example.svg" loading="lazy"/>
.
Say we have several icons rendered as embedded inside HTML. So, instead of:
<svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="100" cy="100" r="90" stroke="black" stroke-width="3" fill="red"/></svg> <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="100" r="90" stroke="black" stroke-width="3" fill="green"/></svg> <svg aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg"><circle cx="10" cy="10" r="90" stroke="black" stroke-width="3" fill="blue"/></svg>
Do this:
<img src="icon.svg" loading="lazy"/> <img src="icon_2.svg" loading="lazy"/> <img src="icon_3.svg" loading="lazy"/>
Note that the above is not applicable when you render <svg>
using <use>
with the reference to the existing <svg>
element on the page.