How to Lazy Load Images
Tags: javascript, html, react
Published: 2020-02-22 19:58:01

<h2> What is lazy loading images? </h2>
<i>Lazy loading is a technique that defers the loading of non-critical resources at page load time. Instead, these resources are loaded when required. Where images are concerned, "non-critical" is often synonymous with "below the fold" images</i>
Lazy Loading defers the loading of an image that is not needed on the page immediately. An image, not visible to the user when the page loads, is loaded later when the user scrolls and the image actually become visible. If the user never scrolls, an image that is not visible to the user never gets loaded.

<h2>It carries two main advantages.</h3>

<h3>1. Performance Improvement</h3>
With lazy loading, we are reducing the number of images that need to be loaded on the page initially. Lesser resource requests mean lesser bytes to download and lesser competition for the limited network bandwidth available to the user. This ensures that the device is able to download and process the remaining resources much faster. Hence, the page becomes usable much sooner as compared to one without lazy loading.

<h3>2. Cost reduction</h3>
The second benefit for us is in terms of delivery costs. Image delivery, or delivery of any other asset, is usually charged on the basis of the number of bytes transferred.

<h2>Lazy Load Images</h2>
<h3>1.)Using Intersection Observer</h3>
The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.

 It lets you register a callback function that is executed whenever an element you wish to monitor enters or exits another element (or the viewport). 

You need to pass option object into Intersection Observer constructor, It has following fields-

<h4>root:-</h4>
The element that is used as the viewport for checking visibility of the target. Defaults to the viewport.
<h4>rootMargin:-</h4>
Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). The values can be percentages. 
<h4>threshold:-</h4>
It can take either a single number or an array of numbers which indicate at what percentage you want to detect and fire callback. If you only want to detect when visibility passes the 50% mark, you can use a value of 0.5. If you pass an array like [0, 0.25, 0.5, 0.75, 1] then callback will run every time visibility passes another 25%. The default is 0 (meaning as soon as even one pixel is visible, the callback will execute).
![intersection Observer Code](https://github.com/ShandilyaPrasanna/Lazy-Load-Images/blob/master/public/imagesDemo/lazyLoad_IO.png?raw=true)


<h3>2.)Using event handlers (Most compatible)</h3>
Using event listener on scroll event and every time user scroll to end of the page we can fire the fetch call for more images.
This method works for all the browser.
<b>Note:-Use intersection observer wherever possible, and fall back to event handlers if the widest possible compatibility is a critical application requirement.</b>
<h3>3.)Native lazy-loading for the web</h3>
Chrome already loads images at different priorities depending on where they're located with respect to the device viewport. Images below the viewport are loaded with a lower priority, but they're still fetched as soon as possible.

In Chrome 76, you can use the loading attribute to completely defer the loading of offscreen images and iframes that can be reached by scrolling:
If lazy load is not enabled in your browser you can enable it here:- <b>chrome://flags/</b>
```
<img src="image.png" loading="lazy" alt="…" width="200" height="200">
<iframe src="https://example.com" loading="lazy"></iframe>
```
Here are the supported values for the loading attribute:

<b>->auto:</b> Default lazy-loading behavior of the browser, which is the same as not including the attribute.
<b>->lazy:</b> Defer loading of the resource until it reaches a calculated distance from the viewport.
<b>->eager:</b> Load the resource immediately, regardless of where it's located on the page.
![Native code](https://github.com/ShandilyaPrasanna/Lazy-Load-Images/blob/master/public/imagesDemo/Native.png?raw=true)

<h2>Demo Time:-<h2>
<h3>This demo shows difference between different approaches discussed above</h3>
First radio button is for Intersection Observer, You can see based on rootMargin only three image request is made on load, 

![Native code](https://github.com/ShandilyaPrasanna/Lazy-Load-Images/blob/master/public/imagesDemo/ezgif.com-video-to-gif.gif?raw=true)

Second is for Native chrome support in this case, out of 100 images on load 20 images are fetched

![Native code](https://github.com/ShandilyaPrasanna/Lazy-Load-Images/blob/master/public/imagesDemo/native.gif?raw=true)

The third one is the default case, in this case, we can see all 100 images are downloaded, even though the user might not scroll that far

![Native code](https://github.com/ShandilyaPrasanna/Lazy-Load-Images/blob/master/public/imagesDemo/none.gif?raw=true)