user1374796
user1374796

Reputation: 1582

jQuery: animate if else scroll function

I have a scroll function set up so when the window scrolls beyond 50px, the .header-wrap div animates from a height of 140px to 70px, ideally what should happen then is when you scroll back less than 50px from the top, the .header-wrap div should animate back from 70px to 140px but this function doesn't seem to be working as it should:
jsFiddle: http://jsfiddle.net/ub8Rb/

HTML:

<div class="header-wrap">hello</div>
<div class="scroll"></div>

CSS:

.header-wrap {
    position: fixed;
    width: 100%;
    height: 140px;
    top: 0;
    left: 0;
    text-align: center;
    background-color: #999;
    z-index: 9999;
}
.scroll {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 4000px;
}

jQuery:

$(document).scroll(function () {
    if (window.scrollY > 50) {
        $(".header-wrap").animate({
            height: "70px"
        }, 500);
    } else {
        $(".header-wrap").animate({
            height: "140px"
        }, 500);
    }
});

This function doesn't seem to be working as I've described above, and not animating the height of the div dependant on how far the window has scrolled. Any suggestions are greatly appreciated!

Upvotes: 0

Views: 11056

Answers (4)

Tim Vermaelen
Tim Vermaelen

Reputation: 7059

What happens is your scroll function will fire rapidly, trying to execute the animate() function, which will add them queued into your browser's memory. If you wait long enough, the queue will reach the end and your animation works as expected.

Easy solution, add stop(true, false) in front of animate()

API: http://api.jquery.com/stop/

You could use a wrapper function to capture duplicated events if you want to control the delay.

var headerwrap = $(".header-wrap"),
    delayedEvent = (function () {
        var timers = {};

        return function (callback, delay, id) {
            delay = delay || 500;
            id = id || "duplicated event";

            if (timers[id]) {
                clearTimeout(timers[id]);
            }

            timers[id] = setTimeout(callback, delay);
        };
    })();

$(document).scroll(function (ev) {
    delayedEvent(function () {
        var h = (window.scrollY > 50) ? 70 : 140;
        headerwrap.stop(true, false).animate({ height: h }, 500);
    }, 500, "scroll event");
});

FIDDLE: http://jsfiddle.net/tive/QskJm/

Upvotes: 1

FiLeVeR10
FiLeVeR10

Reputation: 2165

This one is smooth...

var go = true;
$(window).scroll(function() {
    if ($(this).scrollTop() > 50 && go) {
        $(".header-wrap").stop().animate({height:'70px'}, 500);
        go = false;
    } else if ($(this).scrollTop() < 50 && !go) {
        $(".header-wrap").stop().animate({height:'140px'}, 200);
        go = true;
    }
});

made a fiddle: http://jsfiddle.net/filever10/z5D4E/

Upvotes: 3

Overflow Stack
Overflow Stack

Reputation: 833

Add a stop() to your code, $(".header-wrap").stop().animate, this stops any currently executing animations. Here is a JSFiddle with the modified code: >>>CLICK HERE<<<

Upvotes: 1

Jon Clagg
Jon Clagg

Reputation: 224

This may be a problem of conflicting animations, because if you scroll slowly your example works. Setting a trigger to determine when/if to play the height animation should correct the conflict. Here is an example of this working:

http://jsfiddle.net/ub8Rb/18/

var sizeTrigger = 'tall'; 

$(document).scroll(function () { 
    console.log(window.scrollY);
    if (window.scrollY > 50 && sizeTrigger == 'tall') {        
        $(".header-wrap").animate({
            height: "70px"
        }, 500, function() { 
            sizeTrigger = 'small'; 
            console.log(sizeTrigger);
        }); 
    } else if (window.scrollY < 50 && sizeTrigger == 'small') {
        $(".header-wrap").animate({
            height: "140px"
        }, 500, function() { 
            sizeTrigger = 'tall';
            console.log(sizeTrigger);
        });
    }
});

Upvotes: 1

Related Questions