How to implement a "scroll reveal" effect in Ionic-Angular (v5) found on the ionic homepage

I would like to implement the effect of showing certain elements/components based on the scroll position. This is similar to the page which beautifully reveals elements using a delay and scroll position.

I’ve been able to reproduce something similar using ng-in-viewport but it’s nowhere near as cool as the ionic page.


      [inViewportOptions]="{ partial: true, threshold: [0.5] }"


.activateOnScroll {
  opacity: 0;
  -webkit-transform: translateY(48px);
  transform: translateY(48px);
  transition: .4s opacity,.8s -webkit-transform cubic-bezier(.07,.89,.79,.95);
  transition: .4s opacity,.8s transform cubic-bezier(.07,.89,.79,.95);
  transition: .4s opacity,.8s transform cubic-bezier(.07,.89,.79,.95),.8s -webkit-transform cubic-bezier(.07,.89,.79,.95)
} {
  -webkit-transform: translateY(0);
  transform: translateY(0);
  opacity: 1


  public onIntersection({
  }: {
    target: Element;
    visible: boolean;
  }): void {
    this.renderer.addClass(target, visible ? 'active' : 'inactive');
    this.renderer.removeClass(target, visible ? 'inactive' : 'active');

I don’t find that the renderer correctly captures these events. It does sometimes, misses them sometimes. I’ve got this wired up on a dozen components, it works on most of them, most of the time but it misses a lot.

My guess is that this is perhaps related to ion-content having it’s own scroll container? I’m guessing this because I’ve used ngx-scrollreveal on pure angular projects and it works great but doesn’t work with ionic projects

Maybe someone more familiar with the ionic homepage could show us how to do this within an Ionic Angular app?! I tried searching through the homepage source code but couldn’t see where the active class is being applied in js.

1 Like

If the idea is to just trigger some logic or toggle some class when the elements are in the viewport, you could use intersection observer instead.

  async ngAfterViewInit() {
    const options: IntersectionObserverInit = {
      root: this.lazyImage.nativeElement.closest('ion-content')
    }; = new IntersectionObserver(await this.onObserve.bind(this), options);;

  async onObserve(data: IntersectionObserverEntry[]): Promise<IntersectionObserverCallback> {
    if (data[0].isIntersecting) {
      await this.preload(data[0].target as HTMLImageElement);;

This is a snippet I use to lazy-load images as the user scrolls.
You could adapt this to do something close to what you want.