Fading Up Sections Using Intersection Observer
Tags: javascript, css, beginners, tutorial
Published: 2020-11-17 19:05:49

In this article, I will show you a way to apply fade up to your page sections, using Intersection Observer + CSS.

First of all, we need to know what is Intersection Observer and what it does. In a few words, Intersection Observer is: 

> An API that allows to configure a callback whenever an element intersects either the device's viewport or another specified element. That specified element is called the root element or root for the purposes of the Intersection Observer API.

You could take a look at Intersection Observer documentation at: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API

Now, knowing how Intersection Observer works, the concept of what we want to implement seems pretty simple. Just watching our sections and whenever they intersect the viewport or a certain element, make it fade up.

So, **let's do it!**

First, we need our html markup with the section we want to intersect.

```html
<section class="section fadeup">
  <h1>Section Title</h1>
  <p>Section text..........</p>
</section>
```

We're adding a `fadeup` class, to set the initial styles of this section when still hasn't been intersected:

```css
.fadeup {
   transform: translateY(50px);
   opacity: 0;
   transition-property: transform, opacity;
   transition-duration: 1s;
   transition-timing-function: linear;
 }
```

So, the idea is fading up the section from *50px* below, to its current position, and change the opacity from 0 to 1 when it gets intersected. We're also adding the transition time and timing function.

Now, taking advantage that we are modifying the styles, let's set the final state styles:

```css
.in-view {
     transform: none;
     opacity: 1;
 }
```

The idea is to add the `in-view` class to the section and apply these values when intersection happens. Now let's go for it!

First, in our JS file let set the observer options:

```javascript
  const observerOptions = {
       root: null,
       threshold: 0,
       rootMargin: '0 0 -50px 0'
   };
```

By setting the root we're establishing which element is used as the viewport for checking visibility of the target, if we set it to `null` it is going to check it to the browser viewport.

Threshold is the % of our item visibility, which also depends on rootMargin, by giving it -50px at the bottom meaning we are shrinking the root container, therefore the item needs to be 51px visible in order for the intersection to trigger.

The next step will be to create the observer to the target (in this case, the section) to add the `in-view` class to the section element when we want to intersect, and pass it the `observerOptions` we defined previously.

```javascript
const observer = new IntersectionObserver(entries => {
       entries.forEach(entry => {
           if (entry.isIntersecting) {
               entry.target.classList.add('in-view');
               observer.unobserve(entry.target);
           }
       });
   }, observerOptions);
```

For this example we want to stop observing the target, so we just want it to fade up once. To do so we add `observer.unobserve(entry.target)`.

Last but not least, we need to get our section and put it on observation.

But first, to ensure our elements have been loaded in the DOM, we're adding a DOMContentLoaded listener.

```javascript
window.addEventListener('DOMContentLoaded', (event) => { 

const sections =Array.from(document.getElementsByClassName('section'));

for (let section of sections) {
  observer.observe(section);
}

});
```

So, with this we are observing every element with the section class.

The final result will be: 

{% codepen https://codepen.io/Josedelgadoing/pen/abZKYeB %}

All good so far, now, let's scale. **What if we want to fade up not only the section, but also the children elements inside of it in sequence?**. Let's continue with the previous simple example.

First, we are going to add the fadeup class with the initial states to the children as well, then let's add a `fade-delay` class to the children elements we want to have in sequence.

```html
<section class="section fadeup">
  <h2 class="fadeup fade-delay">Section Title</h2>
  <p class="fadeup fade-delay">Section text..........</p>
</section>
```

For the next step let's modify the styles a bit so, we add the final state properties to sections and children with `fade-up`.

```css
.in-view.fadeup, .in-view .fadeup{ 
    transform: none;
    opacity: 1;
}
```

Then, our JavaScript code. We need to grab the section children to give them animation and a respective delay from each other.

So, while looping the array of sections we could:

```javascript
const sections = Array.from(document.getElementsByClassName('section'));
   for (let section of sections) {
   const fadeups = section.getElementsByClassName('fade-delay');
     for (let count = 0; count < fadeups.length; count++) {
        fadeups[count].setAttribute('style', 'transition-delay: ' + count * 0.5 + 's');
    }
  observer.observe(section);
}
```

By doing this tweak, we loop into the elements inside the section, for those which have `fade-delay` class and give them a `0.5s` delay from the section and each other, due to the `count * 0.5` calculation we did there.

By adding some extra styling, we'll have as result something like:

{% codepen https://codepen.io/Josedelgadoing/pen/dyXKjZN %}