Angular 12 Lazy Load Images Example – Speed Up with Loading Images on Scroll

In this Angular tutorial, we’re going to discuss how to lazy load images only when it comes inside the viable area on the webpage. We’ll use the ng-lazyload-image package module in our Angular 12 application to enable the lazy-loaded feature on images.

Article compatible with Angular version starting 4+ up to latest version including 6,7,8,9,10,11 and 12.

Why use Lazy Loading for Images?

Angular applications with loads of mead images to display may increase the loading time. Which ultimately affects the page performances. Moreover, those images which are not even in view getting loaded in a facile manner.

In that case, we can lazily load the images to show up only when they are in the users’ viable area and load subsequent images as the user scrolls the page.

This solution seems fine, but implementation and writing our own logic to achieve this may take much time. Luckily for the Angular application, we have a very useful package module available named ng-lazyload-image.

Using the ng-lazyload-image module we can load images in several styles and animations. Let’s being the installation with a demo application.

How to Add Lazy Loading Images in Angular App?

Following are the quick steps, we are going to follow to implement Lazy Loading images in a snap. Let’s pack and go ahead.

Create a new Angular Application

Run the following ng command to quickly create a new Angular application using CLI commands:

$ ng new ng-lazyload-image-demo-app
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS

Move to the application directory and open the application inside the Visual Studio Code or any other IDE you prefer.

$ cd ng-lazyload-image-demo-app
$ code .

 

Install the package

Now run the following npm command to install the ng-lazyload-image package module in our application

$ npm install ng-lazyload-image

 

Update App Module

After installation, open the app.module.ts file to import the required module LazyLoadImageModule as shown below:

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LazyLoadImageModule } from 'ng-lazyload-image';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    LazyLoadImageModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

Using LazyLoad Images

There are a number of ways to load images using the Lazy Load configurations. Let’s discuss some important and useful ways to use them in the following sections:

Simple Lazy Loaded Images

You can now simply start using the LazyLoaded images in your application by adding the <img/> tag with [defaultImage] and [lazyLoad]  properties

<img [defaultImage]="defaultImage" [lazyLoad]="image" />

These properties will take the URL of the placeholder default image and the actual image to load and show.

export class AppComponent {
  defaultImage = 'https://miro.medium.com/max/441/1*9EBHIOzhE1XfMYoKz1JcsQ.gif';
  image = 'https://images.unsplash.com/photo-1443890923422-7819ed4101c0?fm=jpg';
}

 

Background Images

We can also use the [defaultImage]="defaultImage" [lazyLoad]="image"  props on a DIV to show them as a background image.

<div style="height: 500px;background-size: cover;" [defaultImage]="defaultImage" [lazyLoad]="image"></div>

 

Loading Dynamic Images using async

We can also  dynamically load images using an Async call through an Observable as shown below:

<img [defaultImage]="defaultImage" [errorImage]="errorImage" [lazyLoad]="image$ | async" />

Here we used the image$ variable to take promise and [errorImage] prop to return the image if promise is rejected.

export class AppComponent {
  title = 'ng-lazyload-image-demo-app';

  defaultImage = 'https://miro.medium.com/max/441/1*9EBHIOzhE1XfMYoKz1JcsQ.gif';
  errorImage = 'https://i.imgur.com/QsFAQso.jpg';
  image = 'https://images.unsplash.com/photo-1443890923422-7819ed4101c0?fm=jpg';

  image$:Promise<any>;

  constructor(){
    this.image$ = this.loadImage(this.image);
  }

  loadImage(src:string) {
    return new Promise((resolve, reject) => {
      resolve(src);
    });
  }
}

 

Lazy Load Images inside the Container

Sometimes, we may have a div container on the page that has its own scrollbar. In that case, we can view images when that container is scrolled to let images show up in the viewport.

<div class="scroll-container" id="my-scroll-container">
  <img *ngFor="let image of images" [defaultImage]="defaultImage" [errorImage]="errorImage" [scrollTarget]="myScrollContainer" [lazyLoad]="image" />
</div>

 

Update the Component class

export class AppComponent {

  myScrollContainer!: HTMLElement;
  images = [
    'https://images.unsplash.com/photo-1467932760935-519284fc87fa?dpr=2&auto=compress,format&fit=crop&w=1199&h=800&q=80',
    'https://images.unsplash.com/photo-1468103933896-2c34a78104c2?dpr=2&auto=compress,format&fit=crop&w=1199&h=799&q=80',
    'https://images.unsplash.com/photo-1471201187657-6406da15e43b?dpr=2&auto=compress,format&fit=crop&w=1199&h=1199&q=80'
  ];
  errorImage = 'https://i.imgur.com/XkU4Ajf.png';
  defaultImage = 'https://www.placecage.com/1000/1000';

  constructor(private elmRef: ElementRef) {}

  ngOnInit() {
    this.myScrollContainer = this.elmRef.nativeElement.querySelector('#my-scroll-container');
  }
}

 

Also, below style to add a scrollbar to the container

.scroll-container{
    height: 500px;
    overflow: scroll;
    border: 2px solid red;
    margin-bottom: 100px;
}

 

Properties

Following are some important properties available:

[lazyLoad] : Takes the URL of image which needs to be shown

[defaultImage] : This takes Image URL which acts like a placeholder to show an image until the actual image is loaded.

[errorImage] : When using Async Observables to return images, this properties takes image URL to show if actual imgae failed to load.

offset : Number of px a image should be loaded before it is in view port

scrollTarget : You will need to set this property if you are using a scroll container and do not propagate the scroll event to window.

customObservable : You can pass your own observable if you need more control over the flow. Can be useful if integrating with other frameworks like ionic.

useSrcset : You can set this to true if you need to lazy load images with srcset attribute, instead of src.
<source> tags are set to use srcset by default, so you don’t need to set this option additionaly.

decode : You can set this to true, the image will be decoded before inserted into the DOM. This can be useful for large images.

debug : See debug for more information.

 

Events

Following are the events available to handle the image using hooks.

onStateChange : You can pass a callback function, which will be called when the image is getting into different state.

Example: <img [lazyLoad]="lazyLoadImage" (onStateChange)="myCallbackFunction($event)">

myCallbackFunction(event: StateChange) {
  switch (event.reason) {
    case 'setup':
      // The lib has been instantiated but we have not done anything yet.
      break;
    case 'observer-emit':
      // The image observer (intersection/scroll/custom observer) has emit a value so we
      // should check if the image is in the viewport.
      // `event.data` is the event in this case.
      break;
    case 'start-loading':
      // The image is in the viewport so the image will start loading
      break;
    case 'mount-image':
      // The image has been loaded successfully so lets put it into the DOM
      break;
    case 'loading-succeeded':
      // The image has successfully been loaded and placed into the DOM
      break;
    case 'loading-failed':
      // The image could not be loaded for some reason.
      // `event.data` is the error in this case
      break;
    case 'finally':
      // The last event before cleaning up
      break;
  }
}

 

Conclusion

In this post, we tried to compile important things quickly, moreover, you can check more details on official documentation for demo and more advanced configurations.

 

Leave a Reply

Your email address will not be published. Required fields are marked *