How to Build Beautiful Page Transitions in Angular

The Original Article can be found on https://www.freecodecamp.org

In today’s world, just having a website is not enough. The website needs to have a clean UI and it needs to be intuitive. And most importantly, it needs to have some sort of interactive element.

Interactivity keeps users glued to your site for longer periods of time. As a result, it increases the chances that users will become customers. Also, longer interaction time leads to a lower bounce rate and a higher ranking on search engines.

One of the most common and basic forms of interaction happens when a user scrolls on your website. But wouldn’t it be quite boring if the user keeps scrolling through your long static page?

In this tutorial, we will have a look at three basic animations that you can implement on scroll. Parallax, fade, and slide animations are the most popular animations devs use to make scrolling more fun. Let’s see how we can build them for our sites.

Before we move further, here are the end results:

Parallax animation

Parallax (View Demo)

Fade animation

Fade (View Demo)

Slide animation

Slide (View Demo)

Project Setup

Prerequisites

We will be using Angular 11 to create our project. And we’ll use VS Code as our IDE.

In order to build the animations, we are going to use the fabulous Green Sock Animation Platform (gsap). It’s one of the best JavaScript animation libraries out there.

Create the project

Create an Angular project by entering the command below. Make sure to enable routing when it asks you.

ng new animations --style css
code animations

This will create a new project named animations with the style format as CSS. Next, it will open the project in VS Code.

Now let’s install gsap. In your VS Code terminal, enter the command below:

npm install --save gsap @types/gsap

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

Lastly, let’s create three components. Enter the commands below:

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

How to set up the routes

Let’s create three separate routes: /parallax/fade, and /scroll. Open your app-routing.module.tsand 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 { }

How to Create Parallax Animation

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

When you create page animations, you typically use sections. So, open your parallax.component.html file and paste in the code below:

<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 three components, we will add styling to the common styles.cssfile.

Open your styles.cssfile and paste in the CSS below:

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;
}

In the above code, we are making the height and width of the section equal to the viewport’s height and width. Second, we are aligning the content in the center of the section. Lastly, we are setting the font style for how we want to display the text.

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

.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 code below in your ngOnInit  function:

// Register 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 to help you understand the code. Message me if you need further explanation.

Finally, add the imports below at the top of your TS file so that you don’t get any compile-time errors:

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.

How to Create Fade Animation

For the fade animation, open the fade.component.html file and paste in the HTML code below:

<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 in the CSS below:

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 will hide all sections except the first one. Also, since we are not moving the sections along with the scroll, we’ll mark its position as fixed.

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

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 to make the code self-explanatory. For any clarifications, please let me know.

Visit http://localhost:4200/fade to see the smooth fading animation as you scroll.

How to Create Slide Animation

This is typically the easiest of the lot to understand and implement.

Open your slide.component.htmlfile and paste in the code below. It’s similar to fade.component.html, except the class is removed from 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>

We don’t need to add any CSS.

Next, open the slide.component.ts file and add the code below:

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
        }
      });
    });
  }
}

Again, I have added the inline comments for a better understanding of the code. For any queries, just reach out to me.

Open http://localhost:4200/slide to see a mesmerizing slide animation as you scroll.

Conclusion

Animations add a lot of value to your site, and they help keep your users engaged. As with all things, don’t go overboard and use animations in moderation. Don’t clutter or mess up the website with heavy images and funky animations. 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.

Lastly, a great thanks to Lorem Picsum for providing such great photos.

If you liked this article, you might also like the below articles:

Note: You can find the whole project on GitHub.

#angular #javascript #web-development

How to Build Beautiful Page Transitions in Angular
10.55 GEEK