css-scroll-animation
Home » CSS » Trigger CSS Animations On Scroll – Add CSS Transition using Intersection Observer API

You might be thinking it’s difficult to do fancy CSS animation with a mouse scroll. But infarct it’s fundamentally much simpler. You just need to tell the browser when to start the animation. Which could be triggered by simple javascript.

If you manage to add a class to your scrolling element, you can actually animate that element or any child element inside that element. So the magic trick here is to add class dynamically on the scroll. This can be done by listening to window scroll events. There is so much you can do with this simple method. Here I have listed my personal favorite methods and libraries to do fancy scroll animations.

Trigger Animations On Scroll Without using the library:

The idea here is to create scrollable sections. This will act as the container of the main element. So We’ll create some sections and give them a class name so javascript can observe those parent sections. This is going to be the base of the HTML structure. It would look something like the below.

<div class="scroll__container">
<section>
<h2>Section 1</h2>
</section>
<section>
<h2>Section 2</h2>
</section>
<section>
<h2>Section 3</h2>
</section>
<section>
<h2>Section 4</h2>
</section>
</div>

Add CSS

We'll just disable the body scroll and enable scroll within .scroll_container because we want to take advantage of snapping while scrolling sections.

This is the simplest version of code that will require understanding the demo. We have the parent element and child elements which will have an active class on the scroll. This method of adding class will enable to trigger CSS animations on scroll.

Just for sake of simplicity, we’ll make the height of the container 100% height so we can enjoy the show, It can, however, be any height depending upon the design. We’ll use a Simple CSS class that would look something like this.

body {
overflow: hidden;
perspective: 1000px;
font-weight:800;
overflow-x: hidden;
}
.scroll__container {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
section {
height: 100vh;
scroll-snap-align: center;
}

Add Javascript

Can I trigger CSS animations on scroll without Javascript?

The short answer is NO. Window scrolling is an event and CSS itself is not capable of detecting event changes as of now. So we must use javascript to measure the scroll and trigger something to which CSS can react. We do it using adding a new class to the section. There are experimental features of chrome that let you do control CSS animation on scroll without javascript. But it's just in experimenting mode right now.

There are two popular and easy ways we can detect scrolling and add class to the section.

1. Add Javascript: Using OffsetTop

var sections = document.querySelectorAll('section');
var container = document.querySelector('.scroll__container');
container.addEventListener('scroll', function () {
sections.forEach((e, i) => {
var top = (e.getBoundingClientRect().top);
if (top == 0) {
e.classList.add('is-inview')
} else {
e.classList.remove('is-inview')
}
});
})
container.dispatchEvent(newCustomEvent('scroll'));

This script just adds a class to the section which is currently in view. This script is not fail-safe because it heavily relies on scroll-snap-type: y mandatory and will work for scrolling top to bottom. This code uses snap scrolling and Offset of the scrolling to detect which element is scrolled all the way to its height. Check-out the demo below to see this script in action. [ GITHUB ]

This demo uses simple js to add class and some CSS transitions. More complex animations can be done using the same add class method. For more control over scrolling sections, there is a better way to detect viewport intersection. Which is explained in the next method.

2. Add Javascript: Intersection Observer

This will give you a usable structure to test. Now comes the meat. The observer javascript:

var sections = document.querySelectorAll('section');
var options = {
rootMargin: '0px',
threshold: 0.25
}
var callback = (entries) => {
entries.forEach((entry) => {
var target = entry.target;
if (entry.intersectionRatio >= 0.25) {
target.classList.add("is-inview");
} else {
target.classList.remove("is-inview");
}
})
}
var observer = new IntersectionObserver(callback, options)
sections.forEach((section, index) => {
observer.observe(section)
})

This will enable you to quickly add some page scroll effect. If this is something you’re looking for, then this should be it. No libraries and no overhead scripts.

But if you want to go a little complex with your implementation, You should consider using professional libraries, which will give you more control and compatibility over few lines of code. I personally like to use libraries because I like controlled scroll animation with my animations.

How animation is triggered on scroll

In the example, we have implemented the IntersectionObserver API method. Now viewport can register a callback function to observe which element enter or leaves the viewport. This could be extremely useful to lazy load big content because content can be loaded only when needed. But we’re just using it for adding /removing classes so we can animate our dom elements.

We can configure callbacks with Intersection Observer API when a target element intersects the parent element.

Intersection observer options:

  • Root: ancestor of the target element(s)
  • rootMargin: margin for the parent element
  • Threshold: value / values of scroll percentage [0 -1]

You can get more understanding of what happens to observed element when scrolling the window:

This works not only within the frame, but try to scroll your browser window and see what happens.

The Threshold value in the above example is set to 0.6, so any element entering the viewport will be observed by the javascript and class can be added using the "isIntersecting" value. Similarly, the class can be removed by small javascript. The demo shows how sections behave when any class is added or removed to themselves when they are in the viewport window.

With this little configuration, you can animate objects in HML. In my example, I have only used CSS Transitions, but we can use @keyframes to animate a variety of animations. There are debts on whether to use transitions or animations, But I use transitions most of the time. I combine them with javascript for control sequence and performance. I have a detailed explanation of how CSS animations work if @keyframes is the way you want to go.

Triggering CSS Transitions On Scroll:

When any class is applied to the parent, we can use different CSS rules on child objects to make a transition. for example: when we have section with no class, we'll have headings opacity set to 0. so the heading H2 will be hidden. When we add class .is-inview to the section, we. can add another rule section.is-inview h2 and have opacity to 1.  we'll use the transition attribute to notify the browser to smoothly transit the property.  in this case, heading H2 will have opacity animation when class .is-invew is applied to its parent section.

section h2{
opacity:0; transition:opacity 500ms;
}
section.is-inview h2{
opacity:1;
}

What else can we do with it?

Trigger CSS Animation on Scroll:

We can rigger animation sequences when the class is applied. Let's say, we have any dummy animation say smoke, and we want it to appear when a section is in view, we can use the same technique to start the animation. with animation-delay, we can have staging animations.

@keyframes smoke {
0% {
opacity: 0;
background-size: 100%;
}
35% {
opacity: 0.7;
}
90% {
opacity: 0.7;
}
100% {
opacity: 0;
background-size: 110%;
}
}
section.is-inview span{
animation: smoke 15s infinite;
}

Personally, I like to start from scratch and I always keep things at their minimum. With this small script, I can create as many transitions as I want and trigger animations on scroll. But in production and when I have time constraints, I use libraries to kickstart my page design process.

So here are my top 10 list of scroll libraries you can use in your next project… 

No, I am kidding.

You don’t actually need 10 libraries to get the job done. You can actually need best suited for your purposes. I mostly use one of these two libraries. They do the trick for me mostly. Here is a short example of what I was able to do with just this little script.

I like to mention some of the libraries though,

AOS : (Animate on Scroll)

For a simple scroll animation bundle, AOS is a great option. You just need to define certain attributes in your code and the library will take care of the rest. AOS works on the same principle defined above, It adds class to the element when we scroll the page. But It is packed with many premade CSS animations that you can trigger on the scroll. The main features of this library are it’s

  • It’s animations
  • Add delays
  • Add repetition
  • Trigger Custom Animation
  • Change directions
  • Configure offsets
  • Easing support

The magical function AOS uses to add a class on the section is

AOS.init();

We’re not using Its data-aos animations to do animations from the book. But we’re just using it’s added class aos-animate to trigger our animations.

ScrollMagic

This library gives even further control over our scroll event. You can go creative with your scroll movement using ScrollMagic. Sure it has a learning curve but it’s better to learn one library that works for all your interactions and micro-interactions.

The benefits of using this library are:

  • Animation based on scroll position
  • Trigger animation by adding class
  • Enable synchronized animation on scroll
  • Pinning element
  • Parallax
  • Easing libraries support
  • Callbacks and many more...

We’re not going to explore all the features on scrollMagic. But We’ll just use the AddClass method and see how creative we could go with it. We can use a simple piece of code to do exactly the same thing vanilla js does.

<script>
var controller = new ScrollMagic.Controller({globalSceneOptions: {duration: '100%'}});

document.querySelectorAll('section').forEach(function(e){
new ScrollMagic.Scene({triggerElement: e})
.setClassToggle(e,"is-inview")
.addIndicators()
.addTo(controller);
})
</script>

Note this library gives us the ability to add debug indicators. Super helpful while developing specific interactions. This gives you better control of our animated elements.

Should You Use Libraries to Trigger CSS Animations on Scroll?

If registering the simple event will give you the ability to animate your elements using CSS, then you should definitely give it a try. But If you’re a newbie then experimenting from the scratch may affect your productivity. You can search the internet for lots of inspiration and samples to kickstart your cool webpage. But Adding a class is the easiest way to trigger CSS animation on scroll.

About The Author

4 thoughts on “Trigger CSS Animations On Scroll – Add CSS Transition using Intersection Observer API

  1. Hi
    Can you help me with one jQuery.I am trying to scroll right div upto the left side div's height or upto bottom Div.But it is not stopping and pushing down the bottom Div.

    Thanks

Your Thoughts On It?

Your email address will not be published. Required fields are marked *

Oh hi there 👋 It’s nice to meet you.

Sign up to receive awesome content in your inbox, every month.

I don’t spam! Read our privacy policy for more info.