Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Activate CSS3 animation when the content scrolls into view

People also ask

How do I enable animation when the content scrolls into view?

The solution is to add the class fade-in-element to elements as they appear in the viewport during a scroll. You can do this with JavaScript. You should add the hidden class to each element you want to animate.

How do I start a viewport animation?

How can I trigger this animation to start once in viewport? What do you mean by "once in viewport"? The best way to do this is to move the animation into a separate class and then add it when your element intersects the viewport (you can use an IntersectionObserver for that).


Capture scroll events

This requires using JavaScript or jQuery to capture scroll events, checking each time a scroll event fires to see if the element is in view.

Once the element is in view, start the animation. In the code below, this is done by adding a "start" class to the element, that triggers the animation.

Updated demo

HTML

<div class="bar">
    <div class="level eighty">80%</div>
</div>

CSS

.eighty.start {
    width: 0px;
    background: #aae0aa;
    -webkit-animation: eighty 2s ease-out forwards;
       -moz-animation: eighty 2s ease-out forwards;
        -ms-animation: eighty 2s ease-out forwards;
         -o-animation: eighty 2s ease-out forwards;
            animation: eighty 2s ease-out forwards;
}

jQuery

function isElementInViewport(elem) {
    var $elem = $(elem);

    // Get the scroll position of the page.
    var scrollElem = ((navigator.userAgent.toLowerCase().indexOf('webkit') != -1) ? 'body' : 'html');
    var viewportTop = $(scrollElem).scrollTop();
    var viewportBottom = viewportTop + $(window).height();

    // Get the position of the element on the page.
    var elemTop = Math.round( $elem.offset().top );
    var elemBottom = elemTop + $elem.height();

    return ((elemTop < viewportBottom) && (elemBottom > viewportTop));
}

// Check if it's time to start the animation.
function checkAnimation() {
    var $elem = $('.bar .level');

    // If the animation has already been started
    if ($elem.hasClass('start')) return;

    if (isElementInViewport($elem)) {
        // Start the animation
        $elem.addClass('start');
    }
}

// Capture scroll events
$(window).scroll(function(){
    checkAnimation();
});

Sometimes you need the animation to always occur when the element is in the viewport. If this is your case, I slightly modified Matt jsfiddle code to reflect this.

jQuery

// Check if it's time to start the animation.
function checkAnimation() {
    var $elem = $('.bar .level');

    if (isElementInViewport($elem)) {
        // Start the animation
        $elem.addClass('start');
    } else {
        $elem.removeClass('start');
    }
}

In order to activate a CSS animation, a class needs to be added to the element when this becomes visible. As other answers have indicated, JS is required for this and Waypoints is a JS script that can be used.

Waypoints is the easiest way to trigger a function when you scroll to an element.

Up to Waypoints version 2, this used to be a relatively simple jquery plugin. In version 3 and above (this guide version 3.1.1) several features have been introduced. In order to accomplish the above with this, the 'inview shortcut' of the script can be used:

  1. Download and add the script files from this link or from Github (version 3 is not yet available through CDNJS, although RawGit is always an option too).

  2. Add the script to your HTML as usual.

    <script src="/path/to/lib/jquery.waypoints.min.js"></script>
    <script src="/path/to/shortcuts/inview.min.js"></script>
    
  3. Add the following JS code, replacing #myelement with the appropriate HTML element jQuery selector:

    $(window).load(function () {
        var in_view = new Waypoint.Inview({
            element: $('#myelement')[0],
            enter: function() {
                $('#myelement').addClass('start');
            },
            exit: function() {  // optionally
                $('#myelement').removeClass('start');
            }
        });
    });
    

We use $(window).load() for reasons explained here.

Updated Matt's fiddle here.


You do not need to capture scroll events anymore

Since 2020, every browser is able to notify if an element is visible in your viewport.

With intersection observer.

I posted the code here: https://stackoverflow.com/a/62536793/5390321


In addition to these answers please consider these points :

1- Checking the element in view has many considerations :
How to tell if a DOM element is visible in the current viewport?

2- If someone wanted to have more control over the animation (e.g. set "the animation type" and "start delay") here is a good article about it :
http://blog.webbb.be/trigger-css-animation-scroll/

3- And also it seems that calling addClass without a delay (using setTimeout) is not effective.


CSS FOR TRIGGER :

<style>
    .trigger{
      width: 100px;
      height: 2px;
      position: fixed;
      top: 20%;
      left: 0;
      background: red;
      opacity: 0;
      z-index: -1;
    }
</style>
<script>
        $('body').append('<div class="trigger js-trigger"></div>');

        $(document).scroll(function () {
 
           $('YOUR SECTIONS NAME').each(function () {

               let $this = $(this);

               if($this.offset().top <= $('.js-trigger').offset().top) {

                   if (!$this.hasClass('CLASS NAME FOR CHECK ACTIVE SECTION')) {
                       $this
                           .addClass('currSec')
                           .siblings()
                           .removeClass('currSec'); 
                   }
               }

           });

        });
</script>