Lazy loading is a website optimization technique in which elements of a page, such as images, are loaded only when they reach a calculated distance from the viewport.
On the other hand, elements that fit into the viewport at the start are instantly loaded. This allows the user to begin interacting with the page as soon as possible.
The GIF above shows the implementation of lazy loading on images. The images visible in the viewport (or within close range) are loaded instantly, while images far below the viewport are only fetched when the user scrolls near them.
In this tutorial, we will cover:
Different ways to implement lazy loading attributes
Though most modern browsers natively support lazy loading on images with the
<img loading=lazy> attribute, older browsers may fall short in supporting the feature. In such cases, the browser would simply ignore the attribute without side effects.
To handle browsers that don’t natively support lazy loading, you can either use a third-party library or a polyfill. In this tutorial, we’ll go with the polyfill approach to build the page shown above.
There are many polyfill options available to help with lazy loading implementation on older browsers. We’ll use a lightweight and highly efficient package called loading-attribute-polyfill to natively implement lazy loading on images and iframes.
<img loading=lazy>. It also boosts the SEO performance of the page by loading the image and iframe contents for search engine crawlers in a timely manner.
We’ll use another polyfill to ensure compatibility all the way down to Microsoft Internet Explorer 9.
Basic example of how to set up lazy loading
The directory structure for this project is going to be very simple.
We’ll start by creating an empty folder for our project. Within it, we’ll create a subfolder named
/images. Then we’ll move in a couple of dog photos that we’ll lazy load on our page.
In addition to the folder
/images, we’ll create the file
index.html for the markup:
project-folder/ ├── images/ │ ├── dog-one.jpg │ ├── dog-two.jpg │ ├── dog-three.jpg │ ├── dog-four.jpg │ ├── dog-five.jpg │ ├── dog-six.jpg │ ├── dog-seven.jpg │ ├── dog-eight.jpg │ ├── dog-nine.jpg │ └── dog-ten.jpg └── index.html
You can use the loading-attribute-polyfill package in two ways. The first option is to install the package via either npm or Bower. Alternatively, you can load the polyfill asynchronously via CDN, a method that is very easy to set up.
For this tutorial, we’ll load the polyfill asynchronously inside the script tag. Go into your project’s
index.html file and include the following base markup:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> <!-- Including other optional polyfills depending on expected browser support --> <script src="https://polyfill.io/v3/polyfill.min.js?flags=gated&features=IntersectionObserver" crossorigin="anonymous" ></script> <script async src="https://cdn.jsdelivr.net/npm/[email protected]/loading-attribute-polyfill.min.js" integrity="sha256-kX73NqVUoUbV0K44kgoqP8P8IZfU0OEjr/afCnK2Mrg=" crossorigin="anonymous"></script> <!-- Ensures that all images appear as block element --> <style> img display: block; </style> </head> <body> <!-- Include images here--> </body> </html>
This code contains links to two polyfills. Here’s why:
First, we downloaded the Intersection Observer API polyfill to enable lazy loading on older versions of Microsoft Edge, Microsoft Internet Explorer 11, or Apple Safari up to 12.0 that don’t natively support this capability.
Afterward, we downloaded loading-attribute-polyfill in parallel with parsing the page. This step supports native lazy loading.
We also defined a style rule that will make each image on the page appear on a new line.
Implementing lazy loading on various image types
How to lazy load simple images
To lazy load simple images, you need to wrap all of the
<img> HTML tags that you’d like to lazy load with a
noscript HTML tag. You also need to set the class attribute as
<body> HTML tag, use the following markup. Remember to point the
src attributes to your own image paths:
Only apply lazy loading to images that fall below the viewport. In our markup, the first
<img> tag will definitely appear on the viewport, so it shouldn’t have the
loading-lazy attribute. The remaining off-screen images are all loaded as the user scrolls close to them.
Furthermore, note that the images should include both
width attributes. If an image’s dimensions are not explicitly set with
width attributes, the browser will not know the size of the image.
Without knowing the image’s dimensions, the browser cannot reserve the appropriate space for it. As a result, the browser may default to 0x0px for any images without set dimensions. This can cause layout shifts as the images load.
In addition, because such images do not take up any space on the screen, the browser may assume that the images all fit into the viewport at the start. In this case, the browser might decide to load everything at once.
By setting the height and width, you essentially push some images off-screen, thus forcing the browser to recognize them as being eligible for lazy loading.
How to lazy load responsive images with
For responsive images, use the
srcset attribute and add three versions of the same image to be displayed on different screen sizes.
Again, make sure to set dimensions to help the browser allocate enough space for the image. This will also ensure the browser displays the correct image version depending on the screen size. In our case, we are using:
- The 140px version (
dog-one-sm.jpg) when the screen width is less than 710px
- The 200px version when the screen width is between 710px and 991px
- The 320px version when the screen width is greater than 991px
How to lazy load an image wrapped in a picture tag
In the case of
<picture>, use the complementary
<source> HTML tags:
For viewports wider than 900px, the browser will load the images specified in the
srcset attribute of the first
<source> tag. If the screen width is smaller than 900px, the browser will use the normal image size from the second
Implementing lazy loading on iframes
For inline frames, use the
<iframe> tag. The
src attribute should be pointed to the document you want to lazy load, and the
loading attribute should be set to
<noscript class="loading-lazy"> <iframe src="https://codepen.io/ubahthebuilder/embed/rNYbaMQ" width="400" height="400" loading="lazy" ></iframe> </noscript>
As with images, you should set the dimensions.
To recap, we built a simple HTML page with a couple of dog photos, loaded the loading attribute JS polyfill from the CDN, and wrapped our off-screen dog photos with this polyfill to enable the lazy loading feature on them.
We also went over how we can use the polyfill along with other attributes such as the
<img> tags, and iframes.
Now you should know how to lazy load your images, even in older browsers that do not support lazy loading natively.
Have a great week.
Debugging code is always a tedious task. But the more you understand your errors the easier it is to fix them.