Fade-in animation on scroll with IntersectionObserver(Vanilla JS)
Tags: javascript, css, saas
Published: 2021-10-01 02:36:52

　When we watch a website that has cool animations, we tend to stay on the website for a long time. 

It could be said that these animation features could help attract visitors to your website.


Today, I'll share with you guys　how　to　implement　fade-in animation on scroll with **Vanilla Javascript**.

Using IntersectionObserver to monitor if the element that you plan to animate is in the browser or not, you can make a fade-in animation that fires when the element enters the browser.
<br>

#Sample & Goals

Here are two samples. 
The first one is added fade-in animation on scroll for one container includes five items.
The second sample is applied fade-in animation for every five-item.
You can try to scroll and check animation again and again.
<br>

{% codepen https://codepen.io/miacan2021/pen/oNzOBXM %}

<br>
#Blueprint

First, prepare an element that you want to apply fade-in animation with HTML. And add '.appear' class. (Class name doesn't matter. Whatever you want.)
Elements with the '.appear' class will be the target of the fade-in animation.

Second, write a fade-in animation with CSS. When the '.inview' class is added to an element with a '.appear', set the *opacity to 1* and *transform: translateY(40px) to none*.

Third, control the '.inview' class using IntersectionObserver of Javascript.
<br>
Throughout this article, we will use the unified class name to explain.
- '.appear' class → It adds to the element's class which you want to apply fade-in animation.
- '.inview' class →　It will be added when the element that has 'appear' class enters the browser. 

Let's try to make a fade-in animation on scroll!
<br>
## Monitor a single element and control classes with IntersectionObserver
<br>
<br>
###1.Prepare the element that has the 'appear' class according to the above blueprint.

```HTML
 <div class="container appear">
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
 </div>
```

This time, I applied the 'appear' class at container div.
<br>

###2.Prepare CSS animation.
<br>
```CSS
.appear {
  transition: all 0.8s;
  opacity: 0;
  transform: translateY(40px);
}

.appear.inview {
  opacity: 1;
  transform: none;
  transition-delay: 0.3s;
}
```

If an element has an 'appear' class, it's applied 'transition','opacity' and 'transform'. 

In this case, I wrote the CSS so that once the 'inview' class is added, the translateY value will disappear. By doing so, the element that has 'appear' class will move upward from 40px down from its normal position.
And then the element can appear to the browser changing 'opacity'.
<br>
###3.Monitor an element and control classes with IntersectionObserver

You can use the IntersectionObserver　to determine if the monitored element is in the browser　or not and add or remove the 'inview' class.

<br>
```Javascript
const appear = document.querySelector('.appear'); 
const cb = function(entries){
  entries.forEach(entry => {
    if(entry.isIntersecting){
      entry.target.classList.add('inview');
    }else{
      entry.target.classList.remove('inview');
    }
  });
}
const io = new IntersectionObserver(cb);
io.observe(appear);
```

I will explain how I am using 'IntersectionObserver'.
<br>
**1.Get the element to be monitored.**

```Javascript
const appear = document.querySelector('.appear'); 
```

   In this case, it's the 'container' class div.
<br>
**2.Write a callback function.**
```Javascript
const cb = function(entries){
  entries.forEach(entry => {
    if(entry.isIntersecting){
      entry.target.classList.add('inview');
    }else{
      entry.target.classList.remove('inview');
    }
  });
}
```

IntersectionObserver passes a callback function as a parameter.
In this code, a callback function is named 'cb'.
To find out which elements have been intersected using 'forEach'.
The 'entry.isIntersecting' can be used for the condition that the element is inside the screen.
And the if-else statement can be used to write code to add or remove classes.
If the element is intersected, add 'inview' class to 'appear' class.

**3.Call the constructor to create an Intersection observer and pass a callback function.**
   
```Javascript
const io = new IntersectionObserver(cb);
```

**4.Specifies the target element to be monitored.**

```Javascript
io.observe(appear);
```
In this code, it's monitoring the element with 'appear' class.
<br>
##Monitor multiple elements(have same class name) and control classes with IntersectionObserver
<br>

###1.Prepare elements that have the 'appear2' class according to the above blueprint.

```HTML
  <div class="container">
        <div class="item appear2">1</div>
        <div class="item appear2">2</div>
        <div class="item appear2">3</div>
        <div class="item appear2">4</div>
        <div class="item appear2">5</div>
  </div>
```

In this second pattern, we will implement an animation in which multiple elements fade-in and out at different times.

I added 'appear2' class to each item.
<br>
###2.Prepare CSS animation using Sass.
```Sass
.appear2 {
    transition: all 0.8s;
    opacity: 0;
    transform: translateY(20px);

  &.inview2 {
      opacity: 1;
      transform: none;
      @for $i from 1 through 5 {
        &:nth-child(#{$i}) {
          transition-delay: $i * 0.1s;
      }
    }
  }
}
```
'.appear2'class is the same styles as '.appear'.
However, '.inview2'　class has for loop section to transition-delay.

In Sass, we can handle Loop conveniently.
I'm going to put transition-delay on each element. 
I use a loop statement to add a time delay for each element to appear one by one.

If you want to write it in CSS, it would be long like this.

```CSS
.appear2.inview2 {
  opacity: 1;
  transform: none;
}

.appear2.inview2:nth-child(1) {
  transition-delay: 0.1s;
}

.appear2.inview2:nth-child(2) {
  transition-delay: 0.2s;
}

.appear2.inview2:nth-child(3) {
   transition-delay: 0.3s;
}

.appear2.inview2:nth-child(4) {
  transition-delay: 0.4s;
}

.appear2.inview2:nth-child(5) {
  transition-delay: 0.5s;
}
```

As you can see, Sass is powerful and useful, and I personally like Sass.
<br>
###3.Monitor multiple elements and control classes with IntersectionObserver

Finally, We will control classes using IntersectionObserver.
In this sample, we need to monitor multiple elements, so we will use a loop statement to implement it.

```Javascript
const items = document.querySelectorAll('.appear2');

const active = function(entries){
    entries.forEach(entry => {
        if(entry.isIntersecting){
        entry.target.classList.add('inview2'); 
        }else{
            entry.target.classList.remove('inview2'); 
        }
    });
}
const io2 = new IntersectionObserver(active);
 for(let i=0; i < items.length; i++){
    io2.observe(items[i]);
 }

```

We have to get multiple elements this time, so I'll use
"querySelector*All*".

```Javascript
const items = document.querySelectorAll('.appear2');
```

This part is the same as the above.
```Javascript

const active = function(entries){
    entries.forEach(entry => {
        if(entry.isIntersecting){
        entry.target.classList.add('inview2'); 
        }else{
         entry.target.classList.remove('inview2'); 
        }
    });
}
const io2 = new IntersectionObserver(active);
```

This last section is different from the previous one.
Since there are multiple elements with the 'appear2' class, we will write the code to monitor all the elements with the 'appear2' class using a loop statement.

```Javascript
 for(let i=0; i < items.length; i++){
    io2.observe(items[i]);
 }
```
This'.observe()' is used in this way '.observe(Elements to be monitored)'.
<br>
If you want to monitor multiple elements that have different classes, you could write like this.

 
```Javascript
const item1 = document.querySelector('.item1');
const child = document.querySelector('.child');
const element = document.querySelector('.element');

///...(omitted)...IntersectionObserver


io2.observe(item1);
io2.observe(child);
io2.observe(element);
```
<br>
**We can make fade-in animation on scroll using IntersectionObserver at last!**


{% codepen https://codepen.io/miacan2021/pen/oNzOBXM %}

This is my first article about tech so I hope you guys could understand it easily.
Thank you.