Chrome 过渡导致重新绘制网格布局中的所有以下元素

efzxgjgh  于 5个月前  发布在  Go
关注(0)|答案(2)|浏览(68)

我想知道以下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"); });
}

个字符
(然而,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;"使用选择器.contents > img添加到div s,可以实现这种期望的行为。但是文档表明广泛使用will-change不是最佳实践。

**可在Chrome v120.0.6099.72上重现。**删除图像元素上的relative似乎可以修复此重绘。

sr4lhrrt

sr4lhrrt1#

您可以将transform-gpu添加到所有<img>标记中:

<img class="relative transition p-1 transform-gpu" src="">

字符串
这将把它们放在单独的层中,并使用GPU进行转换。

hfsqlsce

hfsqlsce2#

问题是Chrome将页面的部分分组到更大的图层中,这通常有助于提高性能,因为它需要跟踪的页面部分较少。缺点是,如果您对其中一个图层的一部分进行动画处理,则整个图层都会重新绘制。
不同的解决方法都迫使Chrome将你应用它们的元素分离到它们自己的更小的层中。当你这样做时,显然有一个性能权衡。一个解决方法是只在过渡运行时将这些CSS修复应用到元素,然后在完成时将其删除。
你可能会发现这篇文章很有趣,它深入到了导致janky渲染的每一个细节。
https://www.sderosiaux.com/articles/2015/03/01/perfmatters/

相关问题