0

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!

4 Answers 4

3

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/

Sign up to request clarification or add additional context in comments.

2 Comments

One thing comes to mind as we're trying to make this as smooth as possible ... calculating the if statement for every scroll event isn't helping much.
how would you smooth that out? without a delay, i want it to fire right away.
1

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);
        });
    }
});

1 Comment

you need to add stop() on your animations, grab the scrollbar and go top and back down a bunch of times and you can see the problem.
1

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<<<

1 Comment

you're right to add stop, however you also need to make sure it only fires once < 50 and once > 50, to make it smooth. Otherwise it will fire tor every scroll action and make the animations choppy.
1

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/

3 Comments

euhm, no it doesn't fire animate on every scroll event. I added the scrollY position as text to check that.
similar to your approach, you're calculating $(this).scrollTop() > 50 && go very rapidly while scrolling. That's something I wouldn't do. Maybe use window.scrollY instead?
because then we're back were we started.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.