Tips for activating multiple CSS animations when scrolling

I am currently working on a project that involves multiple CSS animations. However, I am facing an issue where these animations only occur once when the page initially loads. I would like them to trigger every time the user scrolls past them, regardless of whether they are scrolling up or down the page. Unfortunately, my attempts at using JavaScript to achieve this have been unsuccessful so far. The specific animations include a colored box sliding in from the left and body copy/header elements fading in from the bottom. I aim to stagger these two animations slightly, with the text appearing after the box has slid in halfway. I have tried grouping these divs together to reveal them simultaneously upon scroll, as well as treating them as separate entities within my JavaScript code.

$(window).scroll(function() {
  $('#Featuring_Animated').each(function() {
    var imagePos = $(this).offset().top;
    var imageHeight = $(this).height();
    var topOfWindow = $(window).scrollTop();

    if (imagePos < topOfWindow + imageHeight && imagePos + imageHeight > topOfWindow) {
      $(this).addClass("slide-in-left");
    } else {
      $(this).removeClass("slide-in-left");
    }
  });
});

$('.element-to-hide').css('visibility', 'hidden');
/**
 * ----------------------------------------
 * animation slide-in-left
 * ----------------------------------------
 */

.Featuring_Textbox {
  -webkit-animation: slide-in-left .5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
  animation: slide-in-left .5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
  visibility: visible !important;
}

@-webkit-keyframes slide-in-left {
  0% {
    -webkit-transform: translateX(-1000px);
    transform: translateX(-1000px);
    opacity: 0;
  }
  100% {
    -webkit-transform: translateX(0);
    transform: translateX(0);
    opacity: 1;
  }
}


/**
 * ----------------------------------------
 * animation fade-in-bottom left sections
 * ----------------------------------------
 */

#Featuring_About,
#Featuring_Heading {
  -webkit-animation: fade-in-bottom 0.6s cubic-bezier(0.390, 0.575, 0.565, 1.000) .3s both;
  animation: fade-in-bottom 0.6s cubic-bezier(0.390, 0.575, 0.565, 1.000) .3s both;
  visibility: visible !important;
}

@-webkit-keyframes fade-in-bottom {
  0% {
    -webkit-transform: translateY(50px);
    transform: translateY(50px);
    opacity: 0;
  }
  100% {
    -webkit-transform: translateY(0);
    transform: translateY(0);
    opacity: 1;
  }
}


/**
 * ----------------------------------------
 * animation fade-in-bottom left sections
 * ----------------------------------------
 */

#Featuring_Textbox {
  opacity: 0.9;
  fill: #3B4A5C;
}

.Featuring_Textbox {
  position: absolute;
  overflow: visible;
  width: 640px;
  height: 552px;
  left: 0px;
  top: 0px;
}

#Featuring_About {
  left: 74px;
  top: 238px;
  position: absolute;
  text-align: left;
  font-size: 18px;
  color: white;
}

#Featuring_Heading {
  left: 74px;
  top: 143px;
  position: absolute;
  text-align: left;
  font-size: 40px;
  color: white;
}
<html>
<head>
<script language="JavaScript" type="text/javascript" src="colocation.js"></script>
</head>

<div class="Featuring_Animated element-to-hide" style="visibility:visible;">
  <svg class="Featuring_Textbox">
            <rect id="Featuring_Textbox" rx="0" ry="0" x="0" y="0" width="640" height="552"></rect>
         </svg>
  <div id="Featuring_About">
    <span>Sample Text</span>
  </div>
  <div id="Featuring_Heading">
    <span>FEATURING</span>
  </div>
</div>

</html>

Answer №1

For those who prefer not to use a library, there is an alternative method available. (compiled from various contributors, thank you) Different effects can be assigned to different selectors. The animation will trigger once when a set percentage of the element becomes visible on the screen (isInViewport function - currently set at 35%). It will only trigger once.

// Ensure every element has a "hidden" class if its starting state is hidden (e.g., 'visibility:hidden' for fade-in effects)

var elemList = {elements:[ // Add elements and their corresponding animations here
    {elem:"#home-description", animation:"element-animation"},
    {elem:".nav-item", animation:"slide-in-top"}
]};

var isInViewport = function(el, percentVisible) {
    let
    rect = el.getBoundingClientRect(),
        windowHeight = (window.innerHeight || document.documentElement.clientHeight);

    return !(
        Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-(rect.height / 1)) * 100)) < percentVisible ||
        Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
    )
};



function check(){
    var eArray = elemList.elements;

    if (eArray.length >= 1){  
        eArray.forEach( function(e,i){

            if (e.elem){ // Check if element selector is not empty
                let el = document.querySelectorAll(e.elem);

                if (el.length >= 1){

                    el.forEach( function(x,y){
                        if (isInViewport(x,35)){
                            x.classList.remove("hidden"); // Remove this line if the element should be visible by default
                            x.classList.add(e.animation);
                            eArray.splice(i, 1);
                            
                        }
                    })
                }
            }
        })
    }
}


window.addEventListener('load', function () {
    check();
    document.addEventListener('scroll', function () {
        check();
    })
}, {
passive: true
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

At times, the Ajax response may be lacking in content. However, the response tab in Google

My goal is to retrieve responses from an AJAX call and store them in the global scope for easy access throughout my website. var getOrderStatus = getOrderStatus(), getUserData = getUserData(), orderFormReady = $.when(getOrderStatus, getUserData), ...

Unveil the Expressjs middleware within the API Client

I am currently developing a Nodejs API Client with the following simple form: //client.js function Client (appId, token) { if (!(this instanceof Client)) { return new Client(appId, token); } this._appId = appId; this._token = tok ...

Issues arise when submitting the form on a web page with an MVC 4 partial view, causing the page

Scenario: I am currently working on a C#/MVC 4 project where I have a view that includes a partial view. The main view consists of a form with a submit button, and the partial view is initially hidden but can be displayed by selecting a checkbox. Problem: ...

The screen reader is unable to interpret the text that is visible within the anchor tag

I have an Angular application with a dropdown menu implemented as shown below. When using the NVDA screen reader to navigate, only the content inside the aria-label attribute is being read when tab focused. However, I want it to also read the content (&ap ...

Form an array using the values that are returned

As I iterate through an object and extract elements, my console.log displays: ["item 1"] ["item 2"] ["item 3"] and so on. All I want is to create a new array formatted like this: ["item 1","item 2","item 3"]; ...

Encountering a problem while verifying pattern using regular expressions

I'm facing an issue when manually checking if my inputs match the specified patterns. Below is the function I am using for this check: if (!$element.attr("pattern")) return true; let pattern = $element.attr("pattern"); le ...

Setting up an i18n project in AngularJS

I just embarked on my angularjs journey yesterday with little to no prior knowledge about it. My initial goal is to centralize all the labels for my UI in a file (to facilitate swapping them out for i18n). As far as I know, this can be achieved by importi ...

No information available at the moment

When the data is not present, it displays as "display none"... However, I want it to show "no data found" This is the current code if (a.innerHTML.toUpperCase().indexOf(filter) > -1) { li[i].style.display = ""; } else { li[i].styl ...

What could be causing the if statement to evaluate as false even though the div's style.display is set to 'block'?

Building a react application using createreactapp and encountering an issue with an if statement that checks the CSS display property of a div identified as step1: const step1 = document.getElementById("step-1") if (step1.style.display === 'blo ...

Replacing an existing pie chart with a new one using JavaScript

I created pie charts using chartjs V2.6.0, and everything was working fine until I encountered an issue. Whenever I input new data into the same chart, it keeps displaying the previous data when hovering over. I attempted to fix this by using the $('# ...

Using jQuery to make a PNG image draggable and allow it to overlap with

Can jQuery's Draggable be used with an overlapping PNG image (not as a background image, but for printing purposes)? I attempted using the CSS style "pointer-events: none," however this solution does not function correctly in Internet Explorer. <d ...

How can we use jQuery to change the format of a

I'm working on a project where I want the calendar to display the date that the user picks. Right now, my "{{date}}" is in the format 2016-01-11, but it keeps showing one day before the selected date. I would like it to display as mm/dd/yyyy. I belie ...

Encountering a 404 error when trying to navigate to the next route using the Link component

Having issues with my login route. I've added a Link to the login route inside a button tag in my Navbar component, but when I try to access the route, I'm getting a 404 error page. --app ----pages ------component --------Navbar.js ----- ...

Discovering which chip has wrapped to the next line in Material UI Autocomplete can be found by closely inspect

Currently, I am working with a Material UI autocomplete feature that functions as follows: My goal is to determine when the fourth chip wraps to the next line within the autocomplete so that I can proceed with additional calculations. Is there a method in ...

I am looking to incorporate a feature in my form that allows for multiple file uploads and displaying them

Currently, I have a single file upload input field in my form and it works perfectly fine. However, I am looking to add multiple file inputs to the form as well. I have attempted various methods to integrate the code for multiple file uploads into my form, ...

Will terminating a Google Cloud Storage stream impact network usage?

As part of my project, I am developing a media server that will serve streamable audio files. To reduce the number of requests to Google Cloud Storage, I have implemented a caching system. However, one issue I've encountered is that Chrome sends two ...

What is the method for obtaining a dynamic image URL for the <a href> link?

Here is the default Wordpress generated code for displaying images: <div class="image-section"> <a href="http://websitename.com/wp-content/uploads/2019/06/image-1.jpg" target="_blank" rel="noopener noreferrer"> <img src="http://websit ...

A dynamic modal window built with ReactJS

I am struggling to understand how to make my app function properly. There is a component called ContactAdd that should render the component ModalWindow when clicked. The ModalWindow component requires a parameter called isOpened={this.state.open}. How c ...

The selector often yields varying results when used in a traditional browser versus when it is utilized with Selenium

When using Firefox in the console, I can enter: $("a:contains('tekst')") and it will display: object { length: 1, ... } However, when attempting the same in firefox opened by behat with sellenium, I receive the error message: SyntaxError: An ...

Steps to invoke a function to add an element into a list

Every time a user clicks on a button, I want to generate a new tab. In this tab, when the user clicks again, I want a function to be called like: onclick('+reportname+','+report type+') onclick("'+reportname+'","'+repor ...