Lazy loading images using JS & ReactJS
Tags: webdev, ux, react, javascript
Published: 2024-05-17 18:10:21

We all want the page content to load as soon as possible. When we have a bunch of images, we wish they would load in the order we see them and only load what would be visible to a user.

The default loading of images in a collection is random and load in any order leading to a not so smooth user experience.

I wanted to lazy load the images.

**My Options** to begin with in 2024 - 

1.Native loading - The loading="lazy" attribute natively supported by browsers (https://web.dev/articles/browser-level-image-lazy-loading)
2.Intersection observer - custom implementation
3.React components abstracting the functionality of lazy loading 
* https://www.npmjs.com/package/react-lazy-load-image-component 
* https://www.npmjs.com/package/react-intersection-observer

Native lazy loading worked well for me as I was focussed on Chrome.
https://web.dev/articles/browser-level-image-lazy-loading
Important to have the image width and height specified for this to work well.

For native lazy loading to work in firefox I read a suggestion on stack overflow to put the loading="lazy" attribute before the src attribute in an image tag.
```
<img loading="lazy" src="path/to/myimage.jpg" />
```

**CONS: No Control on the trigger to start loading images**
With native lazy loading there is however no control on the trigger when the images will start loading. Chrome has some defaults for when to trigger the lazy loading based ond on the screen size and the internet speed.
For finer control on the trigger eg start loading images before 100px from the scrolling point, #2 Intersection Observer or #3 components based on the Intersection Observer will give finer control.

Some enhancements to the image conatiner/holding div while the image loads - 

**LQIP - Low Quality Image Placeholder**
We can load a low quality image in place of the heavier/actual image until its loaded.

If you are using React, below is a code snippet to give you an idea,  (I haven't yet taken to functional components preferring the class components with lifecycle methods) :-
```

componentDidMount(){
   this.setState({photoUrl:this.props.lqipUrl});// load the lqip first
    loadImage();//async load the main image
}

const loadImage = async (pUrl)=>{
   const tImage = new Image(pUrl);
   const that = this;
    tImage.onLoad = ()=>{that.setState({photoUrl:pUrl};// change to the main image after loading 
    tImage.src = pUrl;
}

render(){
  return (
     <img src={this.state.photoUrl} loading="lazy" />
  );
}
```
We could also apply some blur effect on the image tag when the LQIP is loaded , when the main image is loaded we can animate the blur to sharpen the image. 


Some good tips on lazy loading https://imagekit.io/blog/lazy-loading-images-complete-guide/

**Dominant color of the image as a background color**
I like the idea of using a background color for the image div while the main image loads incase we dont use a lqip. This background color is a dominant color in the image, so it looks a little seamless when the image with similar colors loads. 
If we use stock photo apis we get the dominant color as an attribute in the API we can use.
I have seen this in action on pexels.com

Cover Image credits - Photo by Samer Daboul from Pexels https://www.pexels.com/photo/close-up-shot-of-printed-photos-1226721/ 

Do share in the comments if you have any other approaches to lazy loading images.