Coder Perfect

How can I tell which way a jQuery scroll event is going?

Problem

I’m searching for something that sounds like this:

$(window).scroll(function(event){
   if (/* magic code*/ ){
       // upscroll code
   } else {
      // downscroll code
   }
});

Any ideas?

Asked by Zach

Solution #1

Compare the current and previous scrollTops.

var lastScrollTop = 0;
$(window).scroll(function(event){
   var st = $(this).scrollTop();
   if (st > lastScrollTop){
       // downscroll code
   } else {
      // upscroll code
   }
   lastScrollTop = st;
});

Answered by Josiah Ruddell

Solution #2

You can accomplish that without keeping track of the previous scroll top, which is required in all the other examples:

$(window).bind('mousewheel', function(event) {
    if (event.originalEvent.wheelDelta >= 0) {
        console.log('Scroll up');
    }
    else {
        console.log('Scroll down');
    }
});

I’m no expert on this, so please do your own research, however it appears that when you use $(element).scroll, the event that is being listened for is a’scroll’ event.

However, if you use bind to expressly listen for a mousewheel event, the originalEvent property of the event parameter to your callback contains different data. WheelDelta is a part of such data. You moved the mousewheel up if it’s positive. If it’s negative, the mousewheel was moved down.

Mousewheel events, I believe, will fire when the mouse wheel turns, even if the page does not scroll; in this case,’scroll’ events are unlikely to be fired. You can use event.preventDefault() at the end of your callback to stop the page from scrolling and utilize the mousewheel event for something other than a page scroll, such as zooming.

Answered by cilphex

Solution #3

Save the previous scroll position, then compare it to the new one to check if it is greater or less.

Here’s how to avoid using global variables (fiddle here):

(function () {
    var previousScroll = 0;

    $(window).scroll(function(){
       var currentScroll = $(this).scrollTop();
       if (currentScroll > previousScroll){
           alert('down');
       } else {
          alert('up');
       }
       previousScroll = currentScroll;
    });
}()); //run this anonymous function immediately

Answered by Skilldrick

Solution #4

From this posting and other answers, there could be three possible solutions.

Solution 1

    var lastScrollTop = 0;
    $(window).on('scroll', function() {
        st = $(this).scrollTop();
        if(st < lastScrollTop) {
            console.log('up 1');
        }
        else {
            console.log('down 1');
        }
        lastScrollTop = st;
    });

Solution 2

    $('body').on('DOMMouseScroll', function(e){
        if(e.originalEvent.detail < 0) {
            console.log('up 2');
        }
        else {
            console.log('down 2');
        }
    });

Solution 3

    $('body').on('mousewheel', function(e){
        if(e.originalEvent.wheelDelta > 0) {
            console.log('up 3');
        }
        else {
            console.log('down 3');
        }
    });

I was unable to try it on Safari.

42 chrome (Win 7)

Firefox 37 has been released (Win 7)

Internet Explorer 11 (Win 8)

Internet Explorer 10 (Win 7)

Internet Explorer 9 (Win 7)

Internet Explorer 8 (Win 7)

Based on the results of the multi-browser test, I chose Solution 3 for common browsers and Solution 1 for Firefox and Internet Explorer 11.

I used this answer to identify Internet Explorer 11.

    // Detect IE version
    var iev=0;
    var ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
    var trident = !!navigator.userAgent.match(/Trident\/7.0/);
    var rv=navigator.userAgent.indexOf("rv:11.0");

    if (ieold) iev=new Number(RegExp.$1);
    if (navigator.appVersion.indexOf("MSIE 10") != -1) iev=10;
    if (trident&&rv!=-1) iev=11;

    // Firefox or IE 11
    if(typeof InstallTrigger !== 'undefined' || iev == 11) {
        var lastScrollTop = 0;
        $(window).on('scroll', function() {
            st = $(this).scrollTop();
            if(st < lastScrollTop) {
                console.log('Up');
            }
            else if(st > lastScrollTop) {
                console.log('Down');
            }
            lastScrollTop = st;
        });
    }
    // Other browsers
    else {
        $('body').on('mousewheel', function(e){
            if(e.originalEvent.wheelDelta > 0) {
                console.log('Up');
            }
            else if(e.originalEvent.wheelDelta < 0) {
                console.log('Down');
            }
        });
    }

Answered by Chemical Programmer

Solution #5

I realize there has previously been an acceptable solution, but I wanted to share what I’m utilizing in case it would be useful to others. With the mousewheel event, I get the same direction as cliphex, but with Firefox support. If you’re doing anything like locking scroll and can’t access the current scroll top, doing it this way is handy.

Here’s a link to a live version.

$(window).on('mousewheel DOMMouseScroll', function (e) {

    var direction = (function () {

        var delta = (e.type === 'DOMMouseScroll' ?
                     e.originalEvent.detail * -40 :
                     e.originalEvent.wheelDelta);

        return delta > 0 ? 0 : 1;
    }());

    if(direction === 1) {
       // scroll down
    }
    if(direction === 0) {
       // scroll up
    }
});

Answered by souporserious

Post is based on https://stackoverflow.com/questions/4326845/how-can-i-determine-the-direction-of-a-jquery-scroll-event