I have some code using jQuery and JavaScript that when you scroll into the windows viewport any element with a css animation class is applied. Now I have a section of my site that is hidden with display: none and when you click a button a simple function runs applying display: none and display: block.
The problem I am having is when I click the button to reveal the hidden content all the animations play at once, when in fact they should continue the document flow and only animate when the users scrolls into the viewport.
I put multiple dummy elements so you can see the effect as you scroll.
How can I work my way around this?
function see_more(){
document.getElementById("hide").style.display = 'block';
document.getElementById("seeMore").style.display =`none`;
document.getElementById("seeLess").style.display =`block`;
}
function see_less(){
document.getElementById("hide").style.display = 'none';
document.getElementById("seeMore").style.display =`block`;
document.getElementById("seeLess").style.display =`none`;
}
jQuery(function($) {
var doAnimations = function() {
var offset = $(window).scrollTop() $(window).height(),
$animatables = $('.animatable');
if ($animatables.length == 0) {
$(window).off('scroll', doAnimations);
}
$animatables.each(function(i) {
$animatable = $(this);
if (($animatable.offset().top $animatable.height() 65) < offset) {
$animatable.removeClass('animatable').addClass('animated');
}
});
};
$(window).on('scroll', doAnimations);
$(window).trigger('scroll');
});
#seeLess{
display: none;
}
#hide{
display: none;
}
/* A N I M A T I O N */
.animatable {
/* initially hide animatable objects */
visibility: hidden;
/* initially pause animatable objects their animations */
-webkit-animation-play-state: paused;
-moz-animation-play-state: paused;
-ms-animation-play-state: paused;
-o-animation-play-state: paused;
animation-play-state: paused;
}
/* show objects being animated */
.animated {
visibility: visible;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
-ms-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-duration: 1s;
-moz-animation-duration: 1s;
-ms-animation-duration: 1s;
-o-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-play-state: running;
-moz-animation-play-state: running;
-ms-animation-play-state: running;
-o-animation-play-state: running;
animation-play-state: running;
}
@keyframes bounceIn {
0% {
opacity: 0;
transform: scale(.3);
}
50% {
transform: scale(1.05);
}
70% {
transform: scale(.9);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.animated.bounceIn {
-webkit-animation-name: bounceIn;
-moz-animation-name: bounceIn;
-o-animation-name: bounceIn;
animation-name: bounceIn;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<div class="container-fluid"><button id="seeMore" onclick="see_more()">See all services</button></div>
<div id="hide">
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
</div>
<div class="container-fluid"><button id="seeLess" onclick="see_less()">See less</button></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
This is occurring for 3 reasons.
The animated style class was never removed when the see less button is clicked, prior to setting the display to none.
- Therefore, the elements hid, but on re-appearing, because they had the animated class, they re-animated at the same time.
When clicking the show more button, all of these will animate at once because when at the end of the page, the browser triggers a scroll event automatically, but the correct offset doesn't update in time.
- Therefore, the browser thinks all the elements have the same offset at the end of the page, so it animates them all
Jquery's scroll event listener stopped firing after reaching the end of the page. Not sure what caused it, but I know they sometimes implement their event listeners different than most browsers.
The fix:
- Replace jquery "scroll" event listener with native javascript/browser API scroll event listener
- Remove animated class whenever the see more or see less button is clicked.
- At the end of the day, we only want the animated class when a user scrolls
(All problems resided in javascript, css and html were fine)
Below is a quick fix version of your javascript code. However, I suggest doing some re-factoring of this version, to remove repeated code.
Let me know if this helped :) !
var doAnimations = function() {
var offset = $(window).scrollTop() $(window).height(),
$animatables = $('.animatable');
if ($animatables.length == 0) {
$(window).off('scroll', doAnimations);
}
$animatables.each(function(i) {
$animatable = $(this);
if (($animatable.offset().top $animatable.height() 65) < offset) {
$animatable.removeClass('animatable').addClass('animated');
}
});
};
function see_more(){
$animatables = $('.animated');
$animatables.each(function(i) {
var offset = $(window).scrollTop() $(window).height(),
$animatable = $(this);
if (($animatable.offset().top $animatable.height() 65) < offset) {
$animatable.removeClass('animated').addClass('animatable');
}
});
document.getElementById("hide").style.display = 'block';
document.getElementById("seeMore").style.display =`none`;
document.getElementById("seeLess").style.display =`block`;
$(window).on('scroll', doAnimations);
}
function see_less(){
$animatables = $('.animated');
$animatables.each(function(i) {
var offset = $(window).scrollTop() $(window).height(),
$animatable = $(this);
if (($animatable.offset().top $animatable.height() 65) < offset) {
$animatable.removeClass('animated').addClass('animatable');
}
});
document.getElementById("hide").style.display = 'none';
document.getElementById("seeMore").style.display =`block`;
document.getElementById("seeLess").style.display =`none`;
}
$(window).trigger('scroll');
window.addEventListener("scroll", doAnimations);
#seeLess{
display: none;
}
#hide{
display: none;
}
/* A N I M A T I O N */
.animatable {
/* initially hide animatable objects */
visibility: hidden;
/* initially pause animatable objects their animations */
-webkit-animation-play-state: paused;
-moz-animation-play-state: paused;
-ms-animation-play-state: paused;
-o-animation-play-state: paused;
animation-play-state: paused;
}
/* show objects being animated */
.animated {
visibility: visible;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
-ms-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-duration: 1s;
-moz-animation-duration: 1s;
-ms-animation-duration: 1s;
-o-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-play-state: running;
-moz-animation-play-state: running;
-ms-animation-play-state: running;
-o-animation-play-state: running;
animation-play-state: running;
}
@keyframes bounceIn {
0% {
opacity: 0;
transform: scale(.3);
}
50% {
transform: scale(1.05);
}
70% {
transform: scale(.9);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.animated.bounceIn {
-webkit-animation-name: bounceIn;
-moz-animation-name: bounceIn;
-o-animation-name: bounceIn;
animation-name: bounceIn;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<div class="container-fluid"><button id="seeMore" onclick="see_more()">See all services</button></div>
<div id="hide">
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
<p class=" animatable bounceIn">Lion Cut</p>
<div class=" animatable bounceIn" style="margin-bottom: 300px;">
<p>This is one of our specialty Services, the Lion Cut. One of our customers favorite cuts,
have your favorite pet looking like a majestic king or queen in no time!
</p>
</div>
</div>
<div class="container-fluid"><button id="seeLess" onclick="see_less()">See less</button></div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>