You can detect a browser scroll event on an arbitrary element with:
element.addEventListener('scroll', function (event) {
// do something
});
I would like to be able to differentiate between vertical scrolling and horizontal scrolling and execute actions for them independently.
I'm currently doing this by stashing the values of element.scrollTop, and element.scrollLeft, and then comparing them inside the event listener. E.g.
var scrollLeft, scrollTop;
element.addEventListener('scroll', function (event) {
if (scrollLeft !== element.scrollLeft) {
// horizontally scrolled
scrollLeft = element.scrollLeft;
}
if (scrollTop !== element.scrollTop) {
// vertically scrolled
scrollTop = element.scrollTop;
}
});
This works fine, however from https://gist.github.com/paulirish/5d52fb081b3570c81e3a I read that reading the scrollLeft or scrollTop values causes a reflow.
Is there a better way to do this without causing a browser reflow on scroll?
I think your code is right, because at the end of the day you need to read one of those properties to find out the scroll direction, but the key thing here to avoid performance problems is to throttle the event, because otherwise the scroll
event fires too often and that is the root cause for performance problems.
So your example code adapted to throttle the scroll
event would be like this:
var ticking = false;
var lastScrollLeft = 0;
$(window).scroll(function() {
if (!ticking) {
window.requestAnimationFrame(function() {
var documentScrollLeft = $(document).scrollLeft();
if (lastScrollLeft != documentScrollLeft) {
console.log('scroll x');
lastScrollLeft = documentScrollLeft;
}
ticking = false;
});
ticking = true;
}
});
Source: https://developer.mozilla.org/en-US/docs/Web/Events/scroll#Example