是否在触发DOMContentLoaded后应用样式?

时间:2017-10-28 12:30:50

标签: javascript html css

考虑以下HTML文档:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        body {
            background: crimson;
        }

        div {
            transition: opacity 5s;
            font-size: 4em;
            opacity: 0;
        }

        .loaded div {
            opacity: 1;
        }
    </style>
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function() {
            document.getElementById('body').className += "loaded";
        })
    </script>
</head>
<body id="body">
<div>
TEST
</div>
</body>
</html>

div应该将其不透明度设置为0,并在不透明度上进行5s过渡。

加载DOM时,会为主体指定一个将div不透明度设置为1的类。

我期待div不透明度在5s内从0过渡到1。但出于某种原因,它会立即发生。

如果我使用setTimemout,则每个都按预期工作:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        body {
            background: crimson;
        }

        div {
            transition: opacity 5s;
            font-size: 4em;
            opacity: 0;
        }

        .loaded div {
            opacity: 1;
        }
    </style>
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function() {
            setTimeout(function() {
                document.getElementById('body').className += "loaded";
            }, 0);
        })
    </script>
</head>
<body id="body">
<div>
TEST
</div>
</body>
</html>

让我想知道在触发DOMContentLoaded事件后加载样式。这是正常行为还是我在这里做错了什么?

2 个答案:

答案 0 :(得分:4)

来自Mozilla Documentation:

  

在完整加载和解析初始HTML文档时会触发 DOMContentLoaded 事件,而无需等待样式表,图像和子帧完成加载。

文档建议您应该使用load事件:

  

一个非常不同的事件 load 应仅用于检测完全加载的页面。

所以你会这样做:

window.addEventListener('load', function() {
        document.getElementById('body').className += "loaded";
});

请注意,我不仅更改了事件名称,还更改了我将侦听器分配给的对象。

答案 1 :(得分:3)

简短版:

您正在进入指定行为不足的领域。我建议您使用load事件来触发转换。

长版:

当元素的CSS属性的计算值发生变化(spec)时会触发CSS过渡,因此不能之前触发样式系统首先计算文档的样式。

样式系统应该在加载相关样式表后对文档进行初始样式传递(即第一次计算计算值) - 否则它将不得不重新执行样式表完成加载后工作。

另一方面,DOMContentLoaded的想法是在解析HTML源时立即触发 - 无需等待任何其他资源(包括样式表)完成加载,因此它naturally can fire before any style was calculated

浏览器有complicated heuristics阻止内联脚本的执行(从而解析和DOMContentLoaded)并确定何时发生初始布局和绘制。脚本可以force reflow/restyle,因此根据特定的网页代码和时间,样式信息可能在脚本运行时可用。我不确定它是否在所有浏览器中都可靠地运行,但强制DOMContentLoaded的布局可能会导致您的转换工作:

div.offsetTop // force layout