Scroll Progress Bar in Angular Applications

In this tutorial, we will create a scroll progress bar to indicate a user about how much of the total page is scrolled and how much is left to scroll.

This scroll bar is generally shown on top of the page so that a user gets to know about the length of the page currently being viewed.

To achieve this we are going to create a custom directive with Host Listener for scroll event on the element where we will add the directive selector.

There can be various scenarios in which the scroll can be implemented on another container rather than the main body container. So it’s better to have a directive which can be added anywhere on the application.

Create ScollprogressDirective directive

Run following NPM generate a command to create a new directive in Angular application

$ ng generate directive directives/scollprogress

Open the ~app/directives/scollprogress.directive.ts file and replace with following code:

// scrollprogress.directive.ts
import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[appScollprogress]'
})
export class ScollprogressDirective {

  constructor() { }

  @HostListener('scroll', ['$event'])
  doSomething(event) {

    var winScroll = event.currentTarget.scrollTop;
    var height = event.currentTarget.scrollHeight - event.currentTarget.clientHeight;
    var scrolled = (winScroll / height) * 100;

    console.debug("Scroll %", scrolled);
    document.getElementById("scrollBar").style.width = scrolled + "%";
  }
}

In the above code @HostListener is a binding scroll event handler. We are getting scrolled page percentage to dynamically add width to scrollBar element.

Add Scroll Bar template

In the app.component.html file add an element to show scroll bar and wrap the <router-outlet> directive with a div then add the directive selector appScollprogress as shown below:

<div class="progress-container">
  <div class="progress-bar" id="scrollBar"></div>
</div>


<div class="router-wrapper" appScollprogress>
  <router-outlet></router-outlet>
</div>

Add CSS Style

To add color and alignment to scroll progress bar add following CSS style in the styles.css file at project root:

.progress-container {
    width: 100%;
    height: 8px;
    background: #ccc;
    overflow: hidden;
  }
  
  .progress-bar {
    background: rgba(237,255,184,1);
    background: -moz-linear-gradient(left, rgba(237,255,184,1) 0%, rgba(97,201,0,1) 100%);
    background: -webkit-gradient(left top, right top, color-stop(0%, rgba(237,255,184,1)), color-stop(100%, rgba(97,201,0,1)));
    background: -webkit-linear-gradient(left, rgba(237,255,184,1) 0%, rgba(97,201,0,1) 100%);
    background: -o-linear-gradient(left, rgba(237,255,184,1) 0%, rgba(97,201,0,1) 100%);
    background: -ms-linear-gradient(left, rgba(237,255,184,1) 0%, rgba(97,201,0,1) 100%);
    background: linear-gradient(to right, rgba(237,255,184,1) 0%, rgba(97,201,0,1) 100%);
    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#edffb8', endColorstr='#61c900', GradientType=1 );
    width: 0%;
    transition-timing-function: ease-out;
    transition: width .5s;
    height: 100vh;
  }

We are done! run your application and put some log data in any of your pages to see it working.

Subscribe
Notify of
1 Comment
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
Maxim Robota
import {Directive, HostListener} from '@angular/core';
@Directive({
  selector: '[appScrollProgress]'
})
export class ScrollProgressDirective {
  constructor(
  ) {}
  @HostListener('window:scroll', ['$event'])
  onWindowScroll(event) {
    const winScroll = event.target.documentElement.scrollTop || event.currentTarget.scrollTop || document.body.scrollTop;
    const height = (event.target.documentElement.scrollHeight || event.currentTarget.scrollHeight ) -
      (event.target.documentElement.clientHeight || event.currentTarget.clientHeight);
    const scrolled = (winScroll / height) * 100;
    document.getElementById('scrollBar').style.width = scrolled + '%';
  }
}

It’s working for me. Good job, dude