Awesome Page Transitions in Angular

In today’s world just having a website is not enough. Firstly, The website should have a clean UI. Secondly, it should be intuitive. Lastly and most importantly, there should be some interactive element .

Interactivity keeps the users glued on your site for a longer period. As a result, it increases the chance of converting a user to a customer. Also, longer interaction time leads to lower bounce rate and hence ranking higher in search engines.

One of the most common and basic form of interaction happens when a user scrolls on your website. Wouldn’t it be quite boring if the user keeps on scrolling through your long static page? In this tutorial we will have a look at 3 basic animations that can happen on scroll. Parallax, Fade & Slide animations are the most popular animations used. Let’s see how we can achieve these animations.

Parallax (View Demo)
Fade (View Demo)
Slide (View Demo)

PROJECT SETUP

Prerequisites

We will be using Angular 11 to create our project. This tutorial can be useful for Vanilla HTML, CSS, JS projects as well.

In order to achieve animations we are going to use the fabulous Green Sock Animation Platform (gsap). It’s one of the best javascript animation library out there.

Create Project and Setup

Create an Angular project by executing the below command. Note: Make sure to enable routing when asked.

ng new animations --style css
code animations

This will create a new project named animations with style format as CSS. Secondly, it will open the project in VS Code. Next, let’s install gsap. In the VS Code terminal execute the below command.

npm install --save gsap @types/gsap

This will install the gsap library and and the typing files via @types/gsap.

Lastly, let’s create 3 components. Execute the below commands.

ng g c parallax
ng g c fade
ng g c slide

Set Up Routes

Let’s create 3 separate routes /parallax, /fade, and /scroll. Open your app-routing.module.ts and add the routes as below.

import { NgModule } from '@angular/core';
import { FadeComponent } from './fade/fade.component';
import { SliderComponent } from './slider/slider.component';
import { ParallaxComponent } from './parallax/parallax.component';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'parallax',
    component: ParallaxComponent
  },
  {
    path: 'slide',
    component: SliderComponent
  },
  {
    path: 'fade',
    component: FadeComponent
  }
];


@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

PARALLAX ANIMATION

Since we have now setup the project, let’s start with the parallax animation.

While creating page animations, sections are usually used. So, open your parallax.component.html file and paste in the below code.

<section>
  <div class="bg"></div>
  <h1>THIS IS MY FIRST PARALLAX SECTION</h1>
</section>
<section>
  <div class="bg"></div>
  <h1>GREAT THAT IT'S WORKING</h1>
</section>
<section>
  <div class="bg"></div>
  <h1>SCROLL MORE TO SEE MORE</h1>
</section>
<section>
  <div class="bg"></div>
  <h1>LOVING THE IMAGES</h1>
</section>
<section>
  <div class="bg"></div>
  <h1>NICE, RIGHT?</h1>
</section>

Let’s add some styling to these sections. Since, we are going to use sections in all 3 components we will add styling to the common styles.css file. Open your styles.css file and paste in the below CSS.

html,
body {
    margin: 0 !important;
}

section {
    position: relative;
    height: 100vh;
    width: 100vw;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    text-shadow: 1px 1px 3px black;
    font-size: 3em;
    font-weight: 400;
}

Above, we are making the height & width of the section equal to the viewport’s height and width. Secondly, we are aligning contents in the center of the section. Lastly, we are setting the font style for how the text will be displayed.

Since, the bg class used in parallax.component.html is specific to parallax we will define it’s properties in parallax.component.css. Open that file and paste the below CSS.

.bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  z-index: -1;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

In order to set the parallax animation we need to add some typescript code. So, open your parallax.component.ts file and add the below code in your ngOnInit function.

// Registr the ScrollTrigger plugin with gsap
gsap.registerPlugin(ScrollTrigger);

//Loop over all the sections and set animations
gsap.utils.toArray("section").forEach((section: any, i) => {
  
  // Set the bg variable for the section
  section.bg = section.querySelector(".bg");

  // Give the backgrounds some random images
  section.bg.style.backgroundImage = `url(https://picsum.photos/${innerWidth}/${innerHeight}?random=${i})`;

  // Set the initial position for the background
  section.bg.style.backgroundPosition = `50% ${-innerHeight / 2}px`;

  // Do the parallax effect on each section
  gsap.to(section.bg, {
    backgroundPosition: `50% ${innerHeight / 2}px`,
    ease: "none", // Don't apply any easing function.
    scrollTrigger: {
      // Trigger the animation as soon as the section comes into view
      trigger: section, 
      // Animate on scroll/scrub
      scrub: true
    }
  });
});

I have added inline comments for the explanation. Let me know in comments if you need any clarifications.

Finally, add the below imports at the top of your ts file so that you don’t get any compile time error.

import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/all';

That’s it! You can now visit http://localhost:4200/parallax to see the beautiful animation like here.

FADE ANIMATION

For the fade animation open the fade.component.html file and paste the below html code

<section class="first">
    <h1>THIS IS MY FIRST FADE ANIMATION</h1>
</section>
<section>
    <h1>GREAT THAT IT'S WORKING</h1>
</section>
<section>
    <h1>SCROLL MORE TO SEE MORE</h1>
</section>
<section>
    <h1>LOVING THE IMAGES</h1>
</section>
<section>
    <h1>NICE, RIGHT?</h1>
</section>

In the fade.component.css paste the below CSS.

section {
    position: fixed !important;
}

section:not(.first) {
    opacity: 0;
    visibility: hidden;
    transform: scale(0.8);
}

We are going to display only one section at a time. So we are hiding all the sections except the first one. Also since we are not moving the sections along with the scroll, it’s position is marked as fixed.

Let’s add the animation code to make the other sections visible on scroll. Open the fade.component.ts file and .

import { Component, OnInit } from '@angular/core';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/all';

@Component({
  selector: 'app-fade',
  templateUrl: './fade.component.html',
  styleUrls: ['./fade.component.css']
})
export class FadeComponent implements OnInit {

  // To maintain which section is being displayed.
  currentSection: any;
  constructor() { }

  ngOnInit(): void {
    // Register the ScrollTrigger with gsap
    gsap.registerPlugin(ScrollTrigger);

    // Get an array of all the sections
    let sections = gsap.utils.toArray("section");

    //Set the first section as the current section
    this.currentSection = sections[0];

    // Stretch out the body height according to however many sections there are. 
    gsap.set("body", { height: (sections.length * 100) + "vh" });

    
    // loop over section to create animations
    sections.forEach((section: any, i) => {
      // Set the background for each section
      section.style.backgroundImage = `url(https://picsum.photos/${innerWidth}/${innerHeight}?random=${i})`;

      // create a ScrollTrigger for each section
      gsap.to(section, {
        scrollTrigger: {

          // use dynamic scroll positions based on the window height
          start: () => (i - 0.5) * innerHeight,
          end: () => (i + 0.5) * innerHeight,

          // when a new section activates (from either direction), set the section accordinglyl.
          onToggle: self => self.isActive && this.setCurrentSection(section)
        }
      });
    });
  }

  // Animates the new section and updates the current section
  setCurrentSection(newSection: any) {
    if (newSection !== this.currentSection) {
      // Hide the current section by fading out
      gsap.to(this.currentSection, { scale: 0.8, autoAlpha: 0 })
      
      // Display the current section by fading in
      gsap.to(newSection, { scale: 1, autoAlpha: 1 });
      
      // Update the current section.
      this.currentSection = newSection;
    }
  }
}

I have added inline comments so as the code to be self explanatory. For any clarity please comment below.

Visit http://localhost:4200/fade to see the smooth fading animation as you scroll. You can view the demo here.

Slide Animation

This is the easiest of the lot to understand and implement. Open your slide.component.html file and paste the below code. It’s almost similar to fade.component.html except the class is removed on the first section.

<section>
    <h1>THIS IS MY FIRST SLIDE ANIMATION</h1>
</section>
<section>
    <h1>GREAT THAT IT'S WORKING</h1>
</section>
<section>
    <h1>SCROLL MORE TO SEE MORE</h1>
</section>
<section>
    <h1>LOVING THE IMAGES</h1>
</section>
<section>
    <h1>NICE, RIGHT?</h1>
</section>

No CSS needs to be added. So, next open the slide.component.ts file and add the below code.

import { Component, OnInit } from '@angular/core';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/all';

@Component({
  selector: 'app-slider',
  templateUrl: './slider.component.html',
  styleUrls: ['./slider.component.css']
})
export class SliderComponent implements OnInit {

  constructor() { }
  ngOnInit() {
    // Register the ScrollTrigger with gsap
    gsap.registerPlugin(ScrollTrigger);

    //Loop over all the sections and set animations
    gsap.utils.toArray("section").forEach((section: any, i) => {

      // Give the backgrounds some random images
      section.style.backgroundImage = `url(https://picsum.photos/${innerWidth}/${innerHeight}?random=${i})`;


      gsap.to(section, {
        scrollTrigger: {
          // Trigger the animation as soon as the section comes into view
          trigger: section,
          
          // Pin the section to give a feeling like slide for next section
          pin: true,

          // Remove the extra pin space added by default
          pinSpacing: false
        }
      });
    });
  }
}

And, again I have added the inline comments for better understanding of code. For any queries do comment below.

Open http://localhost:4200/slide to see some mesmerising slide animation as you scroll. You can view the demo here.

Conclusion

Animations add a lot value in keeping the user on the website. As with all things, keep the use animations within limit. Don’t clutter or mess up the website with heavy images and funky animation. Keep It Simple & Keep It Subtle (KIS & KIS).

In this tutorial we saw how to add simple parallax, fade, and slide animations for page sections. Do you have any great animations in mind or any website with awesome animations. Let me know in comments below.

If you have like this, you might also like the below articles:

Note: You can find the whole project on GitHub.

By arjavdave

Love to be a part of social circle. Always want to eat lots of pasta with red wine. A workaholic and always exploring ways to optimise work and trying out new things.

Leave a comment

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