浏览器渲染原理
浏览器渲染过程:
- 根据HTML构建HTML树(DOM)
- 根据CSS构建CSS树(CSSDOM)
- 将两棵树合并成一棵渲染树(Render tree)
- Layout布局(文档流、盒子模型、计算大小和位置)
- Paint绘制(把边框颜色、文字颜色、阴影等绘制出来)
- Compose合成(根据层叠关系展示画面)
CSS动画优化方法
- 优化js
- 对于动画效果的实现,避免使用setTimeout 或 setinterval,请使用requestAnimationFrame。
- 将长时间运行的 JavaScript 从主线程移到 Web Woker。
- 使用微任务来执行对多个帧的DOM更改。
- 使用 Chrome DevTools的Timeline和JavaScript分析器来评估JavaScript的影响。
- 优化渲染范围
- 降低选择器的复杂性;使用以类为中心的方法,如BEM。
- 减少必须计算其样式的元素数量。
- 优化大型、复杂的布局和抖动
- 布局的作用范围一般为整个文档。
- DOM元素的数量将影响性能;应尽可能避免触发布局。
- 评估布局模型的性能;新版Flexbox一般比旧版Flexbox或基于浮动的布局模型更快。
- 避免强制同步和布局抖动;先读取样式值,然后进行样式更改。
- 优化绘制区域
- 除了transform或opacity属性之外,更改任何属性始终都会触发绘制。
- 应尽可能避免绘制。
- 通过层的提升和动画的编排来减少绘制区域。
- 使用 Chrome DevTools绘制分析器来评估绘制的复杂性和开销;应尽可能降低复杂性并减少开销。
- 优化合成
- 坚持使用transform 和 opacity属性更改来实现动画。
- 使用 will-change 或 translateZ 提升移动的元素。
- 避免过度使用提升规则;各层都需要内存和管理开销。
方法源于网站Paul Lewis (web.dev)
Render树就是指将HTML与CSS中要渲染的内容组合起来,最终构成渲染树
为了构建渲染树游览器大致做了以下的内容:
1.从 DOM 树的根节点开始遍历每个可见节点。
- 某些节点不可见(例如脚本标记、元标记等),因为它们不会体现在渲染输出中,所以会被忽略。
- 某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略,例如,上例中的 span 节点不会出现在渲染树中,因为有一个显式规则在该节点上设置了“display: none”属性。
- 对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。
- 发射可见节点,连同其内容和计算的样式。
如何更新样式
- div.style.background = 'red'
- div.style.display = 'none'
- div.classList.add('red')
- div.remove()直接删掉节点
三种更新方式:
- js/css > 样式 > 布局 > 绘制 > 合成
- js/css > 样式 > 绘制 > 合成
- js/css > 样式 > 合成
-
第一种,全走:div.remove() 会触发当前消失,其他元素relayout
-
第二种,跳过layout:改变背景颜色,直接repaint + composite
-
第三种,跳过layout和paint:改变transform,只需composite。注意必须全屏查看效果,在iframe里看有问题
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 从js/css到最终的合成,理论上中间经过的步骤越少,对性能的要求就越少,所以我们可以通过减少中间的步骤,来达到优化CSS动画的目的。
优化方法来源于这篇文章 Stick to Compositor-Only Properties and Manage Layer Count (web.dev)
我们可以通过CSS Triggers这个网站来查看每个属性分别触发了哪些流程。
我们可以通过打开浏览器开发者工具中的画面闪烁功能来查看浏览器中动画的绘制情况,如果闪烁绿框,就表示该区域动画经过了重新绘制,打开方法如下图所示,在实际应用中,我们应尽量减少动画的重新绘制过程,以达到优化动画性能的目的。
参考文章
练习:跳动的心
transition红心
animation红心