How to Create CSS Animations on Scroll [With Examples]

Oscar Jite Avatar

CSS Scroll animations are a great way to bring boring and static sites to life and give the reader a more interesting, unique, and modern experience.

In this post, you will learn how to trigger CSS animations on scroll. (If you are looking for examples, check out our curated list of CSS text animations)

And… who knows? Maybe you end up doing amazing websites like these scrolling animation websites.

What are CSS Scroll Animations?

Scroll animations are any kind of animation taking place while the visitor scrolls up or down a website. Usually the scrolling animation is triggered when the element comes into view and it can be applied to practically any element such as text, images, and videos.

Our eyes are naturally attracted to movement so this feature will entice and keep the visitor engaged. Adding eye-catching animations to your website will make it stand out from the rest.

Any CSS Scroll animation usually involves the use of a plugin or library but we are going to show you how to achieve this without those. So, let’s get to it.

Scrolling Animation with Vanilla JavaScript

Vanilla JavaScript, despite its fancy name, is not a library, it is just plain old JavaScript. So don’t get confused by the “fancy” name.

1. Setup the Page

First things first, create a web page. Just a simple layout with multiple sections.

<section class="container">
  <h2>Caption</h2>
  <div class="text-container">
    <div class="text-box">
      <h3>Section Text</h3>
      <p>Random text</p>
    </div>
    <div class="text-box">
      <h3>Section Text</h3>
      <p>Random text</p>
    </div>
    <div class="text-box">
      <h3>Section Text</h3>
      <p>Random text</p>
    </div>
  </div>
</section>
Code language: HTML, XML (xml)

2. Styling the Page with CSS

Add style attributes to your page and use CSS to define the scroll animation style, Now you need the class, reveal for the sections you are animating and a new class name, active, for when it’s activated.

.reveal{
  position: relative;
  transform: translateY(150px);
  opacity: 0;
  transition: 2s all ease;
}
.reveal.active{
  transform: translateY(0);
  opacity: 1;
}
Code language: CSS (css)

With this, the reveal elements will be hidden until the active class is added. The transform and transition attributes define the scroll animation style, with this, the sections will fade in from the bottom and move, along the y-axis, towards the top. You can check this CSS Transition guide if you have any doubts.

3. Create JavaScript Functions to Target the Elements

We will need these functions to assign the new class name when they enter the viewport and we need it to trigger CSS animations on scroll.

Start by targeting all the reveal elements using document.querySelectorAll().

function reveal() {
  var reveals = document.querySelectorAll(".reveal")
Code language: JavaScript (javascript)

The scrolling animation needs to be triggered when it comes into view so we need to determine the element’s position on the page, that is, the distance of the element from the top of the viewport.

getBoundingClientRect().top gives us this distance from the top of the viewport and window.innerHeight will give us the height of the viewport.

With this, we can set the conditions using for;

for (var i = 0; i < reveals.length; i++) {
  var windowHeight = window.innerHeight;
  var elementTop = reveals[i].getBoundingClientRect().top;
  var elementVisible = 150;
}

Code language: JavaScript (javascript)

The variable, windowHeight is the height of the viewport, elementTop is the distance of the reveal element from the top of the viewpoint or, the length that has been scrolled, and elementVisible is the height at which the element should be revealed to the user.

You can determine when an element has scrolled a certain number of pixels into the page. Now define a function that displays the elements by adding and removing the active class. For this. use if and else statements. These will set the conditions for triggering the animation

if (elementTop < windowHeight - elementVisible) {
  reveals[i].classList.add("active");
} else {
  reveals[i].classList.remove("active");
}
Code language: JavaScript (javascript)

The complete function will look like this;

function reveal() {
  var reveals = document.querySelectorAll(".reveal");
  for (var i = 0; i < reveals.length; i++) {
    var windowHeight = window.innerHeight;
    var elementTop = reveals[i].getBoundingClientRect().top;
    var elementVisible = 150;
    if (elementTop < windowHeight - elementVisible) {
      reveals[i].classList.add("active");
    } else {
      reveals[i].classList.remove("active");
    }
  }
}

Code language: JavaScript (javascript)

Now we just pass it into an event listener to run it every time the visitor scrolls the page in any direction.

window.addEventListener("scroll", reveal);

// To check the scroll position on page load
reveal();
Code language: JavaScript (javascript)

That’s it! You have achieved CSS scroll animation.

But, what if you want more? Right now, every section has the same uniform animation. Let’s give each section a different scroll animation style.

4. Animate with CSS

First, we will assign classes in the HTML so we can reference them later on in our CSS to create the animations we want.

Here’s how we would do it in our first section:

<section class="container">
    <h2>Caption</h2>
    <div class="text-container reveal fade-bottom">
        <div class="text-box">
            <h3>Section Text</h3>
            <p>Random text</p>
        </div>
        <div class="text-box">
            <h3>Section Text</h3>
            <p>Random text</p>
        </div>
        <div class="text-box">
            <h3>Section Text</h3>
            <p>Random text</p>
        </div>
    </div>
</section>
Code language: HTML, XML (xml)

And the same applies to any other sections we have in our HTML.

Then, in our CSS we can assign them different animations like so:

.reveal {
  position: relative;
  opacity: 0;
}
.reveal.active {
  opacity: 1;
}
.active.fade-bottom {
  animation: fade-bottom 1s ease-in;
}
.active.fade-left {
  animation: fade-left 1s ease-in;
}
.active.fade-right {
  animation: fade-right 1s ease-in;
}

Code language: CSS (css)

Define the animations using Keyframes. The transform style attribute can bring a dynamic feel to your page and it can be added here. Another attribute you can add is transition, which is the time it takes for the element to load completely, but the 1s in the animation attribute achieve the same result.

@keyframes fade-bottom {
  0% {
    transform: translateY(50px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}
@keyframes fade-left {
  0% {
    transform: translateX(-100px);
    opacity: 0;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}
@keyframes fade-right {
  0% {
    transform: translateX(100px);
    opacity: 0;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}
Code language: CSS (css)

You can change the transform values and animation attributes to achieve more variety.

5. Final Result

You could animate individual blocks of text, let each paragraph load one after the other. Just assign the class name to whatever you want, style and animate with CSS, sprinkle a little vanilla Js and watch the magic.

Animating the Navigation Bar on Scroll

To add another practical example of using animations on scroll, we will animate a navigation bar based on the scroll position of the page.

We can use our previous example and add a navigation bar to it. Let’s see how to do it.

Feel free to check out how to create a sticky or fixed navbar if you want to get into more details.

1. Setup the NavBar to animate

First, the HTML:

<nav>
  <a href="#home" class="active">Home</a>
  <a href="#about">About</a>
  <a href="#services">Services</a>
  <a href="#contact">Contact</a>
</nav>
Code language: HTML, XML (xml)

2. Style the NavBar With CSS

a {
  text-decoration: none;
}
ul {
  list-style: none;
}
header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 1000;
  background: #42455a;
  padding: 20px;
  text-align: center;
  border-bottom: 1px solid #00c2cb;
}
header nav a {
  padding: 10px 20px;
  font-size: 2rem;
  color: #e0ffff;
  border-radius: 5px;
  letter-spacing: 0.5px;
}
Code language: CSS (css)

Then you add the link styling for when the animation becomes active, you can combine this with the hover style, it’s your choice;

header nav a:hover,
header nav a.active {
  background: #00c2cb;
  color: #42455a;
  transition: 0.5s ease-out;
  letter-spacing: 2px;
}
Code language: CSS (css)

3. Using JavaScript to Animate Our Navigation Bar

First target all the sections and links;

let section = document.querySelectorAll('section');
let menu = document.querySelectorAll('header nav a');
Code language: JavaScript (javascript)

Just like the first example, you want the navbar to be animated when the section is scrolled into view, for that, create an onscroll event and use forEach to call the function. For this, we need to declare the parameters and set the condition.

window.onscroll = () => {
  section.forEach(i => {
    let top = window.scrollY;
    let offset = i.offsetTop - 150;
    let height = i.offsetHeight;
    let id = i.getAttribute('id');
Code language: JavaScript (javascript)

top is the variable for scrollY, which is the length or number of pixels the viewport has been scrolled. offsetTop is the length of the element from the top of the viewport. offsetHeight is the length of the sections and getAttribute() returns the value of an elements attributes, in this case, the id of the sections.

Next, the conditions for execution so the links become active as you scroll down the page. The section should be inside the viewport so, the offset should be less than the length you scroll and also, the length from the top of the viewport and the length of the section or element should be more than the length you have scrolled;

if (top >= offset && top < offset + height) {
  menu.forEach(link => {
  	link.classList.remove('active');
    document.querySelector('header nav a[href*=' + id + ']').classList.add('active');

Code language: JavaScript (javascript)

So now, when you scroll into a new section, the condition is met and the active attributes will be moved to the next link.

Put it all together and it looks like this;

let section = document.querySelectorAll('section');
let menu = document.querySelectorAll('header nav a');
window.onscroll = () => {
  section.forEach(i => {
    let top = window.scrollY;
    let offset = i.offsetTop - 150;
    let height = i.offsetHeight;
    let id = i.getAttribute('id');
    if (top >= offset && top < offset + height) {
      menu.forEach(link => {
        link.classList.remove('active');
        document.querySelector('header nav a[href*=' + id + ']')
          .classList.add('active');
      });
    }
  });
};
Code language: JavaScript (javascript)

4. Result: CSS Scroll Animation + NavBar!

You can add the smooth scroll-behavior attribute to give your website a truly dynamic feel. Make tweaks to the animation and transform style attributes and see what happens. Add a transition-delay to make it even more dramatic (check how to configure this attribute in this CSS Transition guide)

Conclusion

The scroll animation effect is a popular animation in todays websites and provide them with a modern and more dynamic look.

There are many other ways to create animations on scroll such as using components like fullPage.js that will combine animations and scroll in a beautiful way. Fullpage works by snapping full-screen sections into view when the visitor scrolls creating quite a unique and interesting user experience.

And there are many other cool animations you can use on scroll. Just choose the one that fits your needs and creates the best scrolling experience for your visitors and page.

Was this page helpful?