Reputation: 155
What's wrong with my else function?
I try to hide the sign-up-box when scrollTop =0 but wasn't able to make the opacity to work. The width change gets executed while the opacity one doesn't (alert does pop up so scrolltop position is at 0).
Would love to hear some insights from Jquery gurus. Thanks!!
$(window).scroll(function(){
if( $(window).scrollTop() !== 0 ) {
$('.sign-up-box').animate({
right: '100px',
opacity: 1
});
} else {
$('.sign-up-box').css('opacity', '0.6');
$('.sign-up-box').css('width', '300px');
alert("scrolltop = 0");
}
});
Here is the html for reference:
<div class="list-group sign-up-box">
<a href="#" class="list-group-item active">
<span class="glyphicon glyphicon-check"></span>
<h4 class="list-group-item-heading pull-right">Sign up to our email list</h4>
</a>
</div>
Here is the css for reference:
.sign-up-box {
position: fixed;
right: -250px;
bottom: 100px;
width: 250px;
z-index: 4;
opacity: 0;
box-shadow: 0 6px 12px rgba(0,0,0,.175);
}
Upvotes: 0
Views: 292
Reputation: 155
I did more research regarding the issue and figured that the reason why my css weren't working is because the .animate is being called continuously as we scroll the page (thus .animate is constantly renewed and running) and as a result the animation overrides the css changes (same as what Jimmy said). I also tried using .stop().animate and that works only if i wait long enough for the old animation to complete. Otherwise, if I scroll quickly down and back to top the overriding would occur and I would see no change to the animation.
Regarding David's solution, there is 1 potential drawback, which is .animate being called more than once. I've made some tweak and come up with the following optimized solution:
$(document).ready(function() {
// Keep track of previous scroll position.
var previousPosition = 0;
$(window).scroll(function() {
// If user is scrolling down.
if($(window).scrollTop() > 40) {
// And user is coming from the top.
if(previousPosition <= 40) {
//Then animate.
$('.sign-up-box').animate({
right: '100px',
opacity: 1
}, 400);
}
} else {
// If user is scrolling from the bottom.
if(previousPosition > 40) {
// Then animate.
$('.sign-up-box').stop().animate({
right: '-200px',
opacity: 0
}, 400);
}
}
// Update previous position.
previousPosition = $(window).scrollTop();
});
});
What an interesting exploration regarding .animate in JQuery. Thanks everyone for the help!!!
Upvotes: 1
Reputation: 253
The issue here is a race condition. Say the user isn't scrolled to the top, and we animate. If the user then scrolls to the top when the animation is running, the .css call will modify the style attribute for just that moment, but the still running animation will immediately keep overwriting the "opacity" attribute. The reason why replacing .css with .animate works is that animations queue up (they don't run until other animations are complete). The correct way to do this is to do this:
$('#sign-up-box').stop().css('opacity', '0.6');
Upvotes: 0
Reputation: 5849
Check if the animation is currently running with .is(':animated')
and have your jQuery like so:
jQuery(function($) {
$(window).scroll(function(){
if($(window).scrollTop() > 0) {
if(!$('#sign-up-box').is(':animated')) {
$('#sign-up-box').animate({
right: '100px',
opacity: 1
}, 1500);
}
} else {
$('#sign-up-box').animate({
right: '-250px',
opacity: 0
}, 1500);
}
});
});
Additionnal infos
You can pass an object to .css()
jQuery method if you have several properties to set, like so:
$(this).css({
opacity: 0,
color: '#FF0000'
});
For one property, you can use the shorter version: $(this).css('opacity', '0');
.
Upvotes: 0