javascripthtmlreflow

Is there a way to detect horizontal scroll only without triggering a browser reflow


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?


Solution

  • 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