Search code examples
javascriptscrollmicrosoft-edgekeyboard-eventsarrow-keys

How to slow down the scroll speed in Microsoft Edge using JavaScript?


In Microsoft Edge holding the arrow down key on any web page scrolls the page down at an incredibly fast speed. Although Edge is Chromium-based, Google Chrome is not affected by this.

Here is an example using 250 paragraphs of Lorem Ipsum.

In Chrome this scrolls down by a couple paragraphs per second. In Edge this scrolls down dozens of paragraphs per second.

The arrow up/down keys make for a horrible user experience on our website in Edge.

How can we control the scroll rate of our website in Edge using JavaScript?

Edge:

Chrome:


Solution

  • According to Microsoft they have changed Edge to scroll by a % of the scrollbar, rather than by a fixed pixel amount like Chrome does:

    Chromium browsers use a fixed scroll delta value (100px per mousewheel tick, 40px per scrollbar button click or keyboard arrow press). We are changing this behavior to match previous versions of Microsoft Edge, which use scroller height to compute scroll deltas. Percent based scrolling is a great functional addition making it much easier to navigate smaller scrollers.

    On long pages this makes the page scroll incredibly fast.

    This problem appears to be OS version-specific (see the comments).


    I have tested the following solution and it can be used, regardless of what Windows Scrolling Personality is set to in edge:///flags (enabled or disabled).

    if(window.navigator.userAgent.indexOf('Edg') > -1) {
        document.onkeydown = slowScroll;
        window.lastScrolledUp = 0;
        window.lastScrolledDown = 0;
        window.lastScrolledLeft = 0;
        window.lastScrolledRight = 0;
    }
    
    function slowScroll(e) {
    
        // Don't capture key presses when inside form fields
        if(['datalist', 'input', 'optgroup', 'option', 'select', 'textarea'].indexOf(e.target.nodeName.toLowerCase()) >= 0) {
            return;
        }
    
        // Limit in milliseconds - may be scrolled once per this limit
        var minDelay = 50;
    
        var now = Date.now();
        
        switch(e.key) {
            case 'ArrowUp':
                if(now - window.lastScrolledUp < minDelay) {
                    e.preventDefault();
                    return;
                }
        
                window.lastScrolledUp = now;
            break;
        
            case 'ArrowDown':
                if(now - window.lastScrolledDown < minDelay) {
                    e.preventDefault();
                    return;
                }
        
                window.lastScrolledDown = now;
            break;
        
            case 'ArrowLeft':
                if(now - window.lastScrolledLeft < minDelay) {
                    e.preventDefault();
                    return;
                }
        
                window.lastScrolledLeft = now;
            break;
        
            case 'ArrowRight':
                if(now - window.lastScrolledRight < minDelay) {
                    e.preventDefault();
                    return;
                }
        
                window.lastScrolledRight = now;
            break;
        }
    }
    

    The above code successfully slows down the ludicrously fast scroll rate in Edge. The code ensures that the page cannot be scrolled more than once every 50ms in any direction - the timing is controlled by minDelay.

    To take it one step further and apply this limit to all browsers, simply remove the first line of code (and it's closing brace). This is what we've ended up doing to keep the user experience consistent across browsers.

    This code plays nicely with all of the browsers that I've tested it on: Edge, Chrome & Opera (which are all Chromium-based) + Firefox. It simply introduces a limit to how fast the page can be scrolled using the arrow keys.

    Scrolling using Page Down + Page Up remain unaffected and can still be used (pressed or held) to scroll the page at a fast speed.


    I would welcome and greatly appreciate any better answers that don’t use this sort of trickery if you have any ideas please!