Following Adriano's answer (cannot mention or tag him here, maybe because it is my first ever post on StackOverflow), I managed to implement a pretty short solution for managing a set 3 separate animations for my landing page. Here's what the initial code looked like before my custom solution:
let options = {
root: null,
rootMargin: "0px",
threshold: 0.3,
};
let observer = new IntersectionObserver(callbackFunc, options);
const ELEMENTS = document.querySelectorAll(/*Your elements's tags or classes.*/);
createObservers();
function createObservers() {
Array.from(ELEMENTS).forEach((element) => {
observer.observe(element);
});
}
function callbackFunc(entries, observer) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Your custom code.
}
});
}
Now, regarding my solution it is important to note that, for this to work, I put classes to my elements depending on the animation that I wanted to trigger on them. For example, most of the headings have a fade in effect from below. The class that I used for it was "below", like in this example:
<h1 class="below">My title.</h1>
And the animation along with the class attached to it were declared like this:
@keyframes fadeInFromBelow {
0% {
transform: translateY(8rem);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
.fade-in-from-below {
animation: 1s ease-out 0s 1 fadeInFromBelow;
opacity: 1;
}
Finally, here's what the code looks like with my custom code/solution in it (with some comments to help you understand what's happening). I hope this is useful for someone!:
`
// Declare options to be passed to the observer.
let options = {
root: null,
rootMargin: "0px",
threshold: 0.3,
};
// Declare observer.
let observer = new IntersectionObserver(callbackFunc, options);
// Declare all elements that might be animated, by tagname or classname, in a single variable.
const ELEMENTS = document.querySelectorAll(
"h1,h2,h3,p,details,span,li,input,select,textarea,nav,.header-logo,.ham"
);
// Execute function to generate an observer for each element.
createObservers();
function createObservers() {
// Convert the 'ELEMENTS' variable to an array, there might be another workaround for this, so it might be not necessary but this worked just fine for me.
const list = Array.from(ELEMENTS);
list.forEach((element) => {
observer.observe(element);
});
}
// This is just optional, these are just variables for the classes that are going to be added to the elements in order to trigger whichever animation you defined in them.
const LEFT = "slide-in-from-left";
const RIGHT = "slide-in-from-right";
const BELOW = "fade-in-from-below";
// Finally, the function were your custom code/solution will be.
function callbackFunc(entries, observer) {
entries.forEach((entry) => {
// This declaration is optional, it allowed me to make the code more readable and less cluttered.
const e = entry.target.classList;
// First, we check if the element is intersecting the viewport, based on the 'treshhold' attribute that we declared in the 'options' from above.
if (entry.isIntersecting) {
e.add(e.contains("left") && !e.contains(LEFT) && LEFT);
e.add(e.contains("right") && !e.contains(RIGHT) && RIGHT);
e.add(e.contains("below") && !e.contains(BELOW) && BELOW);
e.remove("no-opacity");
}
});
}
`