Lazy Loading Images
Open the lesson folder
In our starter files, open the index.html page from this lessons folder:
> 8.Lazy-loading
Introduction to lazy loading
When we have a web page with images, sometimes we don't see some, or all of these images when the page first loads. There may be images at the bottom of the page which are out of sight. It would make sense for the user to not have to wait for these images to download before the page loads.
To help with this we will now look at lazy loading. This is a way of delaying, or deferring the loading of images which are not critical.
This is often images which the user does not see, or has to scroll to move into view. An example of this is something like Pinterest. The page can have thousands of images, and loading these all at once would take a long time.
It makes sense to only load what the user can see, then load up more images as the user scrolls. We can even add simple, lightweight, placeholder content while the images are being downloaded.
Lazy loading is not just for images, it exists in other parts of web development too. We can lazy load pretty much any type of content depending on what languages, libraries, or frameworks we are using.
We can lazy load news feeds, articles, social media feeds and generally any other type of content we want. There are multiple ways of doing this, including using JavaScript, but here we will look at how to add lazy loading natively.
Starter folder
For this example, we don’t have any images in a folder, we just have a HTML page with multiple images, each one links to an image hosted elsewhere:
<img
src="https://images.dog.ceo/breeds/hound-basset/n02088238_664.jpg"
alt="dog image 1"
/>
<img
src="https://images.dog.ceo/breeds/samoyed/n02111889_1020.jpg"
alt="dog image 2"
/>
<img
src="https://images.dog.ceo/breeds/buhund-norwegian/hakon2.jpg"
alt="dog image 3"
/>
<img
src="https://images.dog.ceo/breeds/shiba/shiba-1.jpg"
alt="dog image 4"
/>
<img
src="https://images.dog.ceo/breeds/entlebucher/n02108000_187.jpg"
alt="dog image 5"
/>
<!-- ... -->
This can be used to simulate loading up our images from the server when needed.
Loading the images together
We can see these images loading in the browsers network panel.
Most browsers have a similar network panel. In Chrome, you can right click > inspect > and select the Network tab. You will need to refresh to see the results.
You will see all ten of the images loaded at the same time:
But, depending on your display, you may only see 3-5 on the screen. Loading these extra images when not required could slow down the user experience. Especially for slower connections.
The loading attribute
To delay the loading of our images which are out of the viewport, we can add a loading attribute to the images, and set it to be lazy.
Add this attribute for each image after the first three:
<!-- repeat for images 4-10 -->
<img
src="https://images.dog.ceo/breeds/shiba/shiba-1.jpg"
alt="dog image 4"
loading="lazy"
/>
<img
src="https://images.dog.ceo/breeds/entlebucher/n02108000_187.jpg"
alt="dog image 5"
loading="lazy"
/>
<!-- ... -->
Refresh the network panel. You will see nothing changes, all images are still loaded.
There is no change because until the images are loaded, the browser does not know the height and width. It can not tell if the images will be in view, or below the fold which is the bottom part of the browser before we need to scroll down.
To fix this, we can set the image size using CSS:
<title>Lazy loading</title>
<style>
img {
width: 600px;
height: 400px;
}
</style>
</head>
We could add the height and width attributes to the image elements if preferred.
Refresh the network panel again. You should now see a reduction in the amount of images loaded.
You may still see more images loaded than we can see in the browser. For example, you may see three on the screen, but six loaded in the network panel. Chrome can choose to pre-load some extra images which it expects we will need pretty soon.
You can also open the project in another browser to see how many images are loaded.
The remaining images will be loaded as we scroll down the page. You can also see this in the Network panel.
They are still loaded in advance of them being in view as browsers may fetch them earlier so they are ready for the user, how early depends on the connection speed, type of image, and also varies by browser.
And all of these extra images have now been saved from the initial page load time, resulting in a better user experience. And this lazy attribute will help even more as we have more images available, especially if the user scrolls to view.
The eager loading option
If there is an image we know we want to load immediately, regardless if is below the page fold or not, we can set loading to be eager. Update the last image to be eager:
<img
src="https://images.dog.ceo/breeds/retriever-golden/n02099601_7019.jpg"
alt="dog image 10"
loading="eager"
/>
This image will now always be loaded as soon as possible.
The loading attribute can also be used with the picture element too, and we only need to add it to the fallback <img> element, rather than all of the sources for it to take effect.
Placeholder images
But what happens if we scroll faster that the images can be downloaded?
There are some different approaches we can take. We can add a placeholder image that is lower quality and therefore faster to load, using something like the picture element. We could provide one single, generic placeholder image. Or even a solid background color, or pattern using CSS.
There is also JavaScript libraries to help with this, along with plugins if you are using WordPress or other content management systems
A popular option is lazysizes. This uses JavaScript to apply fast and performant lazy loading. It also makes use of the picture element and srcset to create responsive images. It is SEO friendly and also intelligently loads images when needed, based on the browser, the scroll position, and also the network, so it can handle a lot of the hard work for us.
It also allows us to use low quality or blurry images as placeholders.
Installation is available via a script we can download, or, an NPM module. There is no configuration needed, all we need to do is set up our images using provided attributes, such as:
<!-- responsive example with automatic sizes calculation: -->
<img
data-sizes="auto"
data-src="image2.jpg"
data-srcset="image1.jpg 300w,
image2.jpg 600w,
image3.jpg 900w"
class="lazyload" />
We hope this class has gave you something to think about, and also some useful techniques you can use in your future or existing projects. Coming up, we have a challenge for you to test out your new skills.