图层重绘与重排

浏览器在渲染页面时会将DOM分为多个图层,进行样式计算、重排和重绘。重绘只改变外观,不涉及布局,而重排会引发重绘且成本较高。触发重绘的属性包括颜色、阴影等,触发重排的属性涉及尺寸、位置等。常见的优化方案包括使用CSS3的transform和opacity,避免频繁修改DOM样式,以及利用文档碎片和硬件加速。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图层重绘与重排

css图层

浏览器再渲染一个页面时,会将页面分为很多个图层,图层有大有小,每个图层上又一个或多个节点,在渲染DOM的时候,浏览器所做的工作实际上时:
  1. 获取dom分割为多个图层
  2. 对每个图层的节点计算样式的结果(Recalculate style–样式重计算)
  3. 为每个节点生成图形和位置(layout—重排,回流)
  4. 将每个节点绘制填充到图层位图中(paint—重绘)
  5. 图层作为纹理上传到GPU
  6. 组合多个图层到页面上生成最终屏幕图像 (Composite-layers–图层重组)

图层创建的条件

chrome浏览器满足一下任何情况都会创建图层
  1. 拥有3D变换的CSS属性
  2. 使用加速视频解码的节点
  3. 节点
  4. CSS3动画的节点
  5. 用偶遇加速属性的元素(will-change)

重绘(Repaint)

重绘是一个元素外观的改变所触发的浏览器行为,例如outline,背景色等属性,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观,重绘不会带来重新布局,所以不一定伴随重排。

需要注意的是:重绘是以图层为单位,如果图层中某个元素需要重绘,那么整个图层都需要重绘,比如一个图层包含很多节点,其中有个gif图gif图的每一帧,都会重绘整个涂层的其他节点,然后生成最终的图层位图。所以这需要通过特殊的方式来强制gif图属于自己一个图层(translateZ(0)或者translate3d(0,0,0)css3的动画也是意昂(好在大的部分情况浏览器自己会为css3动画的节点创建图层)

重排(Reflow 回流)

渲染对象在创建完成添加到渲染树时,并不包含位置的大小信息,计算这些值的过程称为布局或者重拍

“重绘”不一定需要“重排,比如改变某个元素网页元素的颜色,就只会触发“重绘”,不会触触发“重排“,但是,”重排“必然导致”重绘“,比如改变一个网页元素的位置,就会同时触发”重排“和”重绘“,因为布局改变了

触发重绘的属性

属性影响元素的外观,颜色,阴影,边框就会触发重绘

触发重排的属性

元素的宽高属性,位置,字体大小,字体样式,对齐方式改变了就会引起重排

常见的触发重排的操作

Relflow 的成本相比Repaint成本大的多,DOM树李的每个节点都会有Reflow方法,一个节点的Reflow很有可能导致子节点,甚至父节点以及同级节点的Reflow,在一些高性能的电脑上也许还没什么,但是如果Reflow发生在手机上这个过程事非常痛苦,非常好点的
所以,下面这些操作很大可能会是成本比较高的
当你增加、删除、修改DOM节点时,导致Reflow、Repaint
当你移动DOM的位置
当你Resize窗口的时候(移动端没有这个问题,因为移动端的缩放没有影响布局视口 )
当年你修改网页的默认字体的时,
获取某些属性时(wiidth,height。。。)
> 注:display:none会触发reflow ,而visibility:hidden指挥触发repaint,因为没有发生位置变化

优化方案

如果我们需要使得动画或其他节点渲染的性能提高,需要做的就是减少浏览器在运行时所需要做的工作(j尽量减少234步)
1. 计算需要被加载到节点上的样式结果(Recalcutlate style--样式重计算)
2. 为每个节点生成图形和位置(layout--回流和重布局)
3. 将每个节点填充到图层中(paint setup 和paint--重绘)
4. 组合图层到页面上(composite layers--图层重组)
  1. 元素位置移动变换时尽量使用css3的transform来代替top,left等的造作变换(transform)和透明度(opacity)的改变仅影响涂层的组合
  2. 使用opacity来代替visivility
    (1).使用visibility不触发重排,但是依然重绘
    (2).直接使用opacity即触发重绘,又触发重排(GPU底层设计如此!)
    (3).opacity配合图层使用,既不触发重绘也不会触发重排
    原因:透明度的改变,GPU在绘画时知识简单的降低之前已经画好的纹理的alpha值来表达效果,并不需要整体的重绘。不过这个前提是这个被修改的opacity本身必须是一个图层。
  3. 不要使用table布局
    table-cell
  4. 将多次改变样式属性的操作合并成一次操作
    不要一条一条的修改DOM的样式,预先定义好class,然后修改DOM的className
  5. 将DOM离线后在修改
    由于display属性为none的元素不在渲染树中,对隐藏的元素操作不会英法其他元素的重排,如果要对一个元素经行复杂的操作时,可以先隐藏他,操作完成后在显示,这样旨在隐藏和显示触发两次重排。
  6. 利用文档碎片(documentFragment)------vue使用这种方法提升性能
  7. 要把获取某些dom节点的属性值放在一个循环李当作循环的变量
  8. 动画实现过程,启用GPU硬件加速:transform:tranlateZ(0)
  9. 为动画元素新建图层,提高动画元素的z-index
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值