Scroll animations have now become standard on modern websites. They ensure that content is not immediately visible, but only appears once it enters the browser’s viewport.

Used correctly, such effects can improve the user experience and highlight important content more effectively. At the same time, the implementation should remain efficient and not result in unnecessary calculations with every scroll.

In this article, I’ll show you a simple solution using CSS and JavaScript that requires no additional libraries.

Why not just use the scroll event?

Many developers initially resort to the scroll event and check which elements are visible every time the browser moves.

Whilst this works for a small number of elements, it requires the browser to perform constant calculations.

The JavaScript API ` IntersectionObserver` offers a much more elegant solution. It automatically notifies us when an element enters the browser’s visible area.

This results in less code and, at the same time, better performance.

Preparing the HTML

First, we need an element that is to be animated.

<section class="animate">
    <h2>My headline</h2>
    <p> This content will be displayed as soon as it appears in the viewport. </p>
</section>

CSS for the animation

In its initial state, the element should be invisible and displayed slightly offset downwards.

.animate {
        opacity: 0;
        transform: translateY(40px);
        transition: opacity 0.6s ease, transform 0.6s ease;
    }

    .animate.is-visible {
        opacity: 1;
        transform: translateY(0);
    }

As long as the ‘is-visible’ class is missing, the element remains invisible.

As soon as the class is added, the animation starts automatically.

JavaScript with IntersectionObserver

Now let’s apply the ` animate` class to all the elements.

document.addEventListener('DOMContentLoaded', () =&gt; {
    const elements = document.querySelectorAll('.animate');

    const observer = new IntersectionObserver((entries) =&gt; {
        entries.forEach((entry) =&gt; {
            if (entry.isIntersecting) {
                entry.target.classList.add('is-visible');
            }
        });
    });

    elements.forEach((element) =&gt; {
        observer.observe(element);
    });
});

As soon as an element becomes visible, it is assigned the ‘is-visible’ class.

This triggers the previously defined CSS animation.

Run the animation only once

In most cases, the animation should only occur the first time the element appears.

To achieve this, the element can be removed from the observer once the animation has finished.

document.addEventListener('DOMContentLoaded', () =&gt; {
  
    const elements = document.querySelectorAll('.animate');
  
    const observer = new IntersectionObserver((entries, observer) =&gt; {

        entries.forEach((entry) =&gt; {

            if (!entry.isIntersecting) {
                return;
            }

            entry.target.classList.add('is-visible');

            observer.unobserve(entry.target);

        });

    });

    elements.forEach((element) =&gt; {
        observer.observe(element);
    });

});
New comment

0 comments