为啥 JavaScript 会阻止 CSS 动画和过渡?

Posted

技术标签:

【中文标题】为啥 JavaScript 会阻止 CSS 动画和过渡?【英文标题】:Why are CSS animations and transitions blocked by JavaScript?为什么 JavaScript 会阻止 CSS 动画和过渡? 【发布时间】:2013-02-28 08:54:12 【问题描述】:

更新 2:

在 Chrome 31.0.1650.34 beta 中运行下面的 JSFiddle 现在不会导致所描述的行为,即它不会“在 javascript 启动时冻结”。我只能假设他们已经将 CSS 转换放置在与 JavaScript 和页面的其余部分不同的线程上——好消息! Firefox 25.0 中仍然会出现冻结/阻塞转换。

更新 1:

@IvanCastellanos 提到 CSS 过渡和动画在 android Chrome 上没有被阻止。这是非常有用的信息,也是这个问题的部分动机。

原问题:

对于浏览器供应商来说,这可能更像是一个问题,但这里是:直到现在我从this video(和其他人)那里得到的印象是,过渡 CSS 不透明度不会真正受到任何的影响em> 性能问题。

在视频中,Paul Irish 特别给出了过渡不透明度不会成为问题的印象,并且“任何告诉你其他情况的人都是......错误的”。

好吧,如果是这样的话,this fiddle makes me wrong

鉴于 Paul 的非凡主张,为什么 CSS 过渡会被 JavaScript 阻止? 动画也是如此,这是怎么回事?

(对于那些看不到我所看到的,或者懒得看小提琴的人:我看到一个红色方块使它通过淡入转换大约 1/5,然后冻结为 JavaScript开始,然后方块跳到过渡到完全不透明的末尾,大概是因为在 JavaScript 执行期间已经达到了持续时间。)

鉴于 *** 需要我发布一些代码,因为我链接到 jsfiddle,这里是相关的 JavaScript 和 CSS:

(function () 
    "use strict";

    var isVisible = false;

    function handleClick() 

        var fadingSquare = document.querySelector(".fadingSquare"),
            i;

        if (isVisible === false) 
            fadingSquare.className = fadingSquare.className + " active";

            // Do something intensive in JavaScript for a while
            setTimeout(function () 

                for(i = 0; i < 10000; i += 1) 
                    console.log(i);
                

            , 200);    // Make it occur midway through the CSS transition

            isVisible = true;
         else 
            fadingSquare.className = fadingSquare.className.replace("active", "");
            isVisible = false;
        

    

    document.addEventListener("click", handleClick, false);
());

还有 CSS:

.fadingSquare 
    width: 200px;
    height: 200px;
    background: #F00;
    opacity: 0;
    -webkit-transition-property: opacity;
    -webkit-transition-duration: 1s;


.fadingSquare.active 
    opacity: 1;

【问题讨论】:

“鉴于 *** 需要我发布一些代码,因为我要链接到 jsfiddle,所以这里是相关的 JavaScript 和 CSS” 无论如何这是一个好习惯。跨度> 那么政策有效! 【参考方案1】:

Javascript 在浏览器的 UI 线程上运行。

整个页面被 Javascript 阻止;不仅仅是 CSS 过渡。

【讨论】:

这和我的想法差不多,直到我听到 Paul 等人的声音。声称不会有任何性能问题。 @Matt 转换不透明度时没有任何性能问题。编写垃圾 JavaScript 时会出现性能问题。 哈哈,摸摸。幸运的是,JavaScript 不是我的,而是 YouTube (对你来说有些讽刺)。然而,像上面提到的那样的视频在性能和 CSS 方面给人留下了错误的印象。我总是会在 JS 动画上使用 CSS,但它确实有它自己的陷阱。 BTW console.log 非常昂贵。 Android Chrome 能满足您的预期(在 UI 线程之外运行):phpied.com/css-animations-off-the-ui-thread【参考方案2】:

选择的答案有点过时了。截至今天,在 OSX safari、firefox 和 chrome 上都在与 javascript 不同的线程中运行 css 动画。

【讨论】:

有趣的是,FF 54.1 更新对我来说只是破坏了它,JavaScript 代码现在阻止 非布局转换。 这根本不是真的。在循环完成之前,甚至动画 gif 都无法运行 - 没有,什么都没有,nada。 @BekimBacaj -- 恐怕你错了,已经在运行不需要逐帧布局和/或其他样式计算的 CSS 动画、CSS 过渡和 Web 动画 API 动画即使主线程被阻塞也继续运行。我们在 webapp (AudioNodes) 中使用它,它适用于 Chrome、FF、Edge。 @Dave 因为left 需要布局,它在主线程上运行,因此被你的循环阻塞(你真的不应该为布局相关的属性设置动画)。试试transform,动画不会阻塞。

以上是关于为啥 JavaScript 会阻止 CSS 动画和过渡?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Gmail 会阻止电子邮件中的 CSS?

为啥相同的 css 动画有时会不正确?

如果应用了 css 过渡,为啥动画回调函数会立即触发?

Firefox 和 CSS3 动画 - 为啥我的文本会抖动?

CSS3animation动画为啥会出现抖动效果,怎么解决

为啥我的 CSS 动画会消耗这么多资源?