21 Jul

Fast and smooth scroll for Chrome under Linux

Since Chrome (And Chromium for that matter) is not willing to implement a usable website scrolling under Linux (For the reason why just google for “slow scroll chrome linux”), i implemented my own solution to avoid using plugins that inject 5MB of code (No joke, i am looking at you, smoothscroll.net!) to do the same job these couple of lines below do:

(function() {
    const speed = 6, // speed of the animation; 1 = no animation; > 1.0 animation where higher number is slower
        height = 4; // scroll height per wheel step; higher number = bigger scroll height

    let scrollAmount = 0,
        targetElement,
        myReq;
    const ignoreDomElements = ['BODY', 'HTML', '#document', undefined],
        elementGetOverflow = (element) => window.getComputedStyle(element).getPropertyValue('overflow-y'),
        scrollStep = () => {
            // calculate delta speed relative to scroll amount
            const delta = scrollAmount > 0 ? Math.ceil(scrollAmount / speed) : Math.floor(scrollAmount / speed);
            // deduct delta from scroll amount
            scrollAmount -= delta;
            // if delta is given scroll page
            if(delta !== 0) targetElement.scrollBy({ top: delta, behavior: 'auto' });
            // if scroll amount left request next animation frame
            if(scrollAmount !== 0) myReq = requestAnimationFrame(scrollStep);
        };

    window.addEventListener('wheel', event => {
        // cancel event to prevent browser from scrolling
        event.preventDefault();
        event.returnValue = false;
        // if an scrollable element is in the bubble chain use it for scroll animation
        let scrollElement = event.path.find(element => ((!ignoreDomElements.includes(element.nodeName) && 
                (elementGetOverflow(element) === 'scroll' || elementGetOverflow(element) === 'auto') && 
                element.scrollHeight > element.clientHeight)));
        if(!scrollElement) scrollElement = window;
        // add wheel delta to scroll amount if same direction and element, otherwise overwrite
        if(Math.sign(scrollAmount) === Math.sign(event.deltaY) && targetElement === scrollElement) {
            scrollAmount += event.deltaY * height;
        } else {
            scrollAmount = event.deltaY * height;
            targetElement = scrollElement;
        }
        // if scroll amount given start animation
        cancelAnimationFrame(myReq);
        if(scrollAmount !== 0) myReq = requestAnimationFrame(scrollStep);
    }, { passive: false });
})();

Just inject this code with one of the many available JS Injectors you can get on the Chrome Web Store (i always used this one since it has its code published on GitHub), or if you are familiar with extensions write your own extension to inject it.

You can play around with the “speed” and “height” variables in the beginning to adopt it to your needs.

Please note that this code was only developed and tested for Chrome and Chromium browsers, also since it is simulating what the browser should do natively in JS it will never be as efficient.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.