csscss-animationschromiumhardware-acceleration

Is it possible to turn off all CSS animations in Chrome?


I have a weird issue where if I play an animation on one of my 3 monitors, YouTube videos on any other monitor crashes. I did fix this by disabling hardware acceleration in chrome://flags, but a new update in Chrome recently made the issue come back, and I haven't found a way to fix it yet. Animations occur on places like Facebook ("Someone is typing a comment...") or basically any website with a animation-duration CSS property on something (spinners are probably the most used form of animations I guess).

I can verify this simply by placing this CSS on any page:

* {
  animation-duration: 0s !important;
}

Boom instantly all my videos play perfectly. No issues what so ever. I could add this to an userscript (or make a tiny extension), and I don't think it would mess up too much, but I'm more interested in knowing if there's a Chrome flag that can disable animations completely? I don't know if animation-duration works for any animation.


Solution

  • Allow me to answer my own question. Setting animation-duration to 0s !important seems to be working. However, I added animation-play-state: paused for good measure as well.

    I made an userscript, and found that it doesn't target the Shadow DOM, so I have to traverse through every element, check if it's a shadow root, and then add the CSS. Since elements can be added to a page dynamically, I decided to do this every second. So far I cannot see a performance difference, even on pages with a lot of elements.

    Install TamperMonkey (Chrome) or GreaseMonkey (Firefox) to use this:

    // ==UserScript==
    // @name         Disable all animations
    // @version      1.0
    // @author       mortenmoulder
    // @include      *
    // @grant        GM_addStyle
    // @grant        GM_addElement
    // ==/UserScript==
    
    //remove animations globally
    GM_addStyle("* { animation-duration: 0s !important; animation-play-state: paused; }");
    
    var ignoreElements = [];
    
    //remove animations inside shadow DOM elements
    function findShadowRoots(elements) {
        for (var i = 0; i < elements.length; i++) {
            if(elements[i].shadowRoot) {
    
                if(ignoreElements.includes(elements[i].shadowRoot) == false) {
                    GM_addElement(elements[i].shadowRoot, 'style', { textContent: '* { animation-duration: 0s !important; animation-play-state: paused;' });
                    ignoreElements.push(elements[i].shadowRoot);
                }
    
                findShadowRoots(elements[i].shadowRoot.querySelectorAll("*"));
            }
        }
    }
    
    //remove animations every 1 second
    setInterval(() => {
        var allNodes = document.querySelectorAll('*');
        findShadowRoots(allNodes);
    }, 1000);