理论
样式计算
第一步,匹配一系列的样式选择器
第二步,取出所有匹配后的样式规则,构造RenderStyle
步骤
我们的解决思路是
-
减少样式计算的相互作用,即样式重新计算
什么是 Recalculate Style?在浏览器每一帧的渲染流程中,由于 DOM 增删改等因素变化,需要重新计算受影响节点的样式,这一过程在 Chrome DevTools 中被称为 Recalculate Style。我们在排查系统页面性能问题时发现,在影响 DOM 节点数过多的情况下,Recalculate Style 通常会花费较长的时间。 -
使用性能更好的样式选择器
保持简单,使用class选择器。如果的样式选择器存在逻辑.content:nth-last-child(-n+1) .text
,浏览器就需要花时间去计算你说的是哪个元素。
edge可以在这里查看选择器的性能 -
减少样式计算涉及的元素数量
旧的浏览器就没有这种优化,要注意维护自己的DOM结构树,简单较小的DOM结构是优于复杂而大的DOM结构。
对于较新的浏览器,比如Chromium blink有一个叫失效集(Invalidation Set)的优化,它主要用来标记页面中哪些元素需要重新计算样式。
举个例子,如果我们使用.selection *
这种 CSS Selectors给元素动态添加新的样式,会让浏览器认为整个后代元素都需要重新计算样式,失去失效集的优化,从而导致整个页面卡顿。user- select的变更可能也会导致整个情况(不确定) 。
chrome可以这里可以查看受影响的节点数量
参考文档
https://web.dev/reduce-the-scope-and-complexity-of-style-calculations/#reduce-the-number-of-elements-being-styled
应用
这是一个很好的排查样式计算拖累性能的样例:https://moderndevtools.com/lessons/11。如果能打开这个网站,可以不看下面的述说。
简述
排查youtube的性能问题。
-
确定造成性能卡顿的操作;
-
打开Chrome Performance面板录制该操作造成的结果,开始分析;
-
着眼于有标红的最大这块,可以看Summary显示这块渲染时长占比很大,基本可以确定就是这里的卡顿,只有3FPS;
-
在时间轴上点击Recalculate Style,发现这里触发了样式计算,影响了3827个元素,跳转到问题行,在这一行打断点;
6. 发现它是在移除这class样式
7. 在Source面板,搜索这个样式,在顶层元素移除这个样式,直接导致其几千个子元素重新计算样式。
解决方法
- 使用简单路径短的CSS的选择器,删除button的样式。不要通过操作父元素的class去达到影响child Element的效果。
- 使用js直接操作样式,但可能导致可维护性降低。