How can I determine the direction of a jQuery scroll event?
Check current scrollTop
vs previous scrollTop
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
// downscroll code
} else {
// upscroll code
}
lastScrollTop = st;
});
Existing Solution
There could be 3 solution from this posting and other answer.
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');
}
});
Multi Browser Test
I couldn't tested it on Safari
chrome 42 (Win 7)
- Solution 1
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
- Solution 2
- Up : Not working
- Down : Not working
- Solution 3
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
Firefox 37 (Win 7)
- Solution 1
- Up : 20 events per 1 scroll
- Down : 20 events per 1 scroll
- Solution 2
- Up : Not working
- Down : 1 event per 1 scroll
- Solution 3
- Up : Not working
- Down : Not working
IE 11 (Win 8)
- Solution 1
- Up : 10 events per 1 scroll (side effect : down scroll occured at last)
- Down : 10 events per 1 scroll
- Solution 2
- Up : Not working
- Down : Not working
- Solution 3
- Up : Not working
- Down : 1 event per 1 scroll
IE 10 (Win 7)
- Solution 1
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
- Solution 2
- Up : Not working
- Down : Not working
- Solution 3
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
IE 9 (Win 7)
- Solution 1
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
- Solution 2
- Up : Not working
- Down : Not working
- Solution 3
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
IE 8 (Win 7)
- Solution 1
- Up : 2 events per 1 scroll (side effect : down scroll occured at last)
- Down : 2~4 events per 1 scroll
- Solution 2
- Up : Not working
- Down : Not working
- Solution 3
- Up : 1 event per 1 scroll
- Down : 1 event per 1 scroll
Combined Solution
I checked that side effect from IE 11 and IE 8 is come from
if else
statement. So, I replaced it withif else if
statement as following.
From the multi browser test, I decided to use Solution 3 for common browsers and Solution 1 for firefox and IE 11.
I referred this answer to detect IE 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');
}
});
}
You can do it without having to keep track of the previous scroll top, as all the other examples require:
$(window).bind('mousewheel', function(event) {
if (event.originalEvent.wheelDelta >= 0) {
console.log('Scroll up');
}
else {
console.log('Scroll down');
}
});
I am not an expert on this so feel free to research it further, but it appears that when you use $(element).scroll
, the event being listened for is a 'scroll' event.
But if you specifically listen for a mousewheel
event by using bind, the originalEvent
attribute of the event parameter to your callback contains different information. Part of that information is wheelDelta
. If it's positive, you moved the mousewheel up. If it's negative, you moved the mousewheel down.
My guess is that mousewheel
events will fire when the mouse wheel turns, even if the page does not scroll; a case in which 'scroll' events probably are not fired. If you want, you can call event.preventDefault()
at the bottom of your callback to prevent the page from scrolling, and so that you can use the mousewheel event for something other than a page scroll, like some type of zoom functionality.