使用overflow-y时减少滚动抖动:滚动;

时间:2016-09-01 01:36:15

标签: html css performance google-chrome google-chrome-devtools

我有一个2列布局,右栏是一个可滚动的结果列表,最多有200个项目结果(基本上只有一个ul overflow-y: scroll;设置)

我发现当您滚动时,右栏会导致一些jank(在低端硬件上特别明显)。

在Chrome时间轴中,我可以看到一些主要的"更新层树"我滚动列。 有什么方法可以弄清楚为什么"更新层树"是如此冗长,CSS属性影响速度最快? 当我点击它时 - 只是告诉我它运行的时间和其他信息。

我的每个人都有一些表现不佳的CSS(例如过滤器,变换,盒子阴影等) - 如果我逐个删除每个SASS文件,它会提高滚动性能(并且一旦删除所有CSS,最终会删除jank),但很明显很难确定哪些css属性没有执行此操作。

我想知道我是否遗漏了铬时间轴中可能对此有所帮助的内容?

我尝试使用will-change CSS属性将滚动提升为不同的图层/强制硬件加速 - 但这并没有太大的区别。

滚动时也没有执行javascript事件。

限制少于200件物品不是一个选择。

我已经设置了一个这样的例子(我知道它有更长的项目列表,但这仅用于演示目的): https://github.com/jooj123/jank/blob/master/scroll.html

真正有趣的是,如果我删除overflow-y: scroll;(在上面的示例中的.map-search__结果中),滚动变得非常平滑并且jank消失 - 为什么这会产生如此大的影响?

这是Chrome时间轴(基本上只有很长时间"更新层树"部分): enter image description here

修正:

Paul's answer about will-change: transform is spot on,特别是这个花絮帮助:

  

"添加will-change:transform;。一旦添加,"重新绘制滚动" rect已经不见了。"

但要小心,因为它不会总是适用,具体取决于您的代码库,检查滚动性能问题指示器以确保"重新绘制滚动"关闭,对我来说,我还必须禁用在其中一个子div中设置的-webkit-clip-path属性(在我的实际代码库中 - 而不是在提供的演示中),请参阅:

enter image description here

2 个答案:

答案 0 :(得分:26)

我试了your test page并看一看。

首先,对于滚动性能问题,我喜欢翻阅“渲染”面板中的一些复选框:

enter image description here

我们可以立即看到这个div被称为“重新滚动”。然后,您可以在实验“图层”面板中验证:

enter image description here

(我在树中右键单击并选择“显示内部图层”btw)

现在大的“更新层树”成本通常是由很多层或一些尺寸非常大的层引起的。在这种情况下,我们真的没有。但是我们确实有一个滚动图层,它不会被合成滚动。

复合滚动==快速滚动==通常是默认值。但在这样的情况下,我们回到“主线程滚动”,这真的很慢而且很糟糕。从好的方面来说,crbug.com/381840即将修复,应自动修复此测试用例。好极了!但我们现在可以解决它。

解决方法

你确实提到你试过will-change并且它没有效果,但是自己尝试一下效果很好。它属于overflow设置的元素,在本例中为.map-search__results选择器。添加will-change: transform;。一旦添加,“重新绘制滚动”矩形就消失了。然后用时间轴进行测量,它会更好。

这是一个前/后视图:

enter image description here link to viewer

祝你好运!

答案 1 :(得分:4)

如果在滚动时您的问题明显可见,您可以在开发人员工具中打开时间轴样式标签,取消选中适用的样式在样式选项卡中逐个查看元素,看看它如何影响滚动。这样,您可以独立测试每个样式规则,而不是整个CSS文件。如果您在CSS中使用 sourcemaps ,您应该可以轻松地在实际的CSS文件中找到违规规则并进行调整。

如果您不熟悉使用样式标签:打开Chrome开发者工具,请使用检查工具(开发人员窗格的左上角)选择您怀疑可能会给您带来问题的项目。所选元素关联或覆盖的所有样式都将列在样式选项卡中。然后你可以逐个关闭它们。您也可以使用检查器深入挖掘嵌套项目的深度。

<强>更新

我在编辑后删除了代码并仔细查看了它。我注意到你的溢出就在你的ul项目上。就个人而言,我从来没有在ul上使用溢出(通常更喜欢像div这样的容器),所以出于好奇,我从overflow-y:scroll删除了ul并将其放入在ul的包含div .right-content(并将其高度设置为100%),并且janky滚动消失了。

至于为什么,我只能推测,但我认为它与您滚动的项目数量有关。当您的溢出在UL上时,您将直接滚动所有这些子li项。当它在包含div时,你实际上只滚动ul,所以我相信这个过程在计算移动项目的定位时确定的数学要少得多。 1 div定位调整与数百个li进行调整。

paint comparison

如果您比较上图中的时间轴,您会看到差异。顶部的是overlflow-y:scrollul的原始版本。您可以将鼠标悬停在更新树过程中的所有小行上,并看到有数百个项目正在绘制。这些是您的li项。第二个时间轴是我从ul中删除溢出并将其应用于包含div的版本。您可以在此时间轴中看到更新树过程只有一个要绘制的项目是ul。如果您查看项目的尺寸,您也会看到尺寸的差异。