考虑以下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事件后加载样式。这是正常行为还是我在这里做错了什么?
答案 0 :(得分:4)
在完整加载和解析初始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