我想知道以下HTML文档中过度重绘的原因和解决方案。在 Chrome 上,重绘可以在
devtool -> rendering panel -> Paint flashing
中可视化。
for (const el of document.querySelectorAll(".contents > img")) {
el.addEventListener("mouseenter", function() { this.classList.add("easy-in-out", "scale-150", "scale", "z-20"); });
el.addEventListener("mouseleave", function() { this.classList.remove("easy-in-out", "scale-150", "scale", "z-20"); });
}
<div class="grid grid-cols-2" style="width: 410px">
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
</div>
<script src="https://cdn.tailwindcss.com"></script>
(但是,Chrome 似乎无法在 iframe 内显示“Paint flashing”,因此我还提供了下面的最小单文件片段,或者在线访问 https://jjyyxx.github.io/grid-repaint /)
<!DOCTYPE html>
<html>
<body style="width: 410px;">
<div class="grid grid-cols-2">
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
<div class="contents"><img class="relative transition p-1" src="https://picsum.photos/200"></div>
</div>
<script src="https://cdn.tailwindcss.com"></script>
<script>
for (const el of document.querySelectorAll(".contents > img")) {
el.addEventListener("mouseenter", function() { this.classList.add("easy-in-out", "scale-150", "scale", "z-20"); });
el.addEventListener("mouseleave", function() { this.classList.remove("easy-in-out", "scale-150", "scale", "z-20"); });
}
</script>
</body>
</html>
当您
mouseleave
一个图像元素时,淡入淡出过渡将导致其所有后续图像元素重新绘制。对于许多图像或一些大图像,此行为会导致丢帧。
由于布局没有改变,在我看来,只有悬停的元素应该被重新绘制。如果使用选择器
style="will-change: scale;"
将 div
添加到 .contents > img
,则可以实现所需的行为。但文档表明,广泛使用 will-change
并不是最佳实践。
可在 Chrome v120.0.6099.72 上重现。 删除图像元素上的
relative
似乎可以修复此重绘问题。
transform-gpu
添加到所有 <img>
标签中:
<img class="relative transition p-1 transform-gpu" src="">
这会将它们放在不同的层中,并使用 GPU 进行转换。