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.
<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:
.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:
.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:
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.
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.
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:
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.
<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
.
.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:
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:
Top comments (2)
Liked it. Nice work.
Hi good job !
But the transition delay isn't working in your example