数据结构论坛

首页 » 分类 » 常识 » CSS重排Reflow和重绘Repain
TUhjnbcbe - 2023/7/30 20:15:00

dad

一、什么是重排(回流)Reflow和重绘Repaint

1.重排(回流)

重排(回流):当渲染render树中的一部分或者全部因为大小边距、布局等问题发生改变而需要DOM树重新计算的过程,每个页面至少需要一次重排,就是在页面第一次加载的时候。

2.重绘

当元素的一部分属性发生改变,如外观、背景、颜色等不会引起布局变化,只需要浏览器根据元素的新属性重新绘制,使元素呈现新的外观叫做重绘。

3.页面渲染过程

浏览器加载,解析,渲染页面,分为五个步骤:

1.浏览器将获取的HTML文档解析成DOM树;2.处理CSS标记,构成层叠样式表模型(CSSOM);3.将DOM和CSSOM合并为渲染树(rendertree);4.渲染树的每个元素的内容都是计算过的,称之为布局layout;5.将渲染树上的各个节点绘制到屏幕上,称之为绘制painting;

浏览器下载完页面中的所有组件——HTML标记、JavaScript、CSS、图片之后会解析生成两个内部数据结构——DOM树和渲染render树。DOM树表示页面结构,渲染树表示DOM节点如何显示。DOM树中的每一个需要显示的节点在渲染树种至少存在一个对应的节点(隐藏的DOM元素disply值为none在渲染树中没有对应的节点)。渲染树中的节点被称为“帧”或“盒”,符合CSS模型的定义,理解页面元素为一个具有填充边距、边框和位置的盒子。一旦DOM和渲染树构建完成,浏览器就开始显示(绘制)页面元素。当DOM的变化影响了元素的几何属性(宽或高),浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会因此受到影响。浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。这个过程称为重排。完成重排后,浏览器会重新绘制受影响的部分到屏幕,该过程称为重绘。

所以说,第四步(重新生成布局)+第五步(重新绘制)是最耗时的部分,这两步合起来,就是我们通常所说的渲染。

网页生成的时候,至少会渲染一次。

在用户访问的过程中,还会不断重新渲染。

重新渲染需要重复之前的第四步(重排)+第五步(重绘)或者只有第五个步(重绘)。

也就是说,重绘不一定需要重排(比如颜色的改变),重排必然导致重绘(比如改变网页位置)

二、引起重排(回流)Reflow和重绘Repaint的属性

1.引起重排的情况

很显然,每次重排,必然会导致重绘,那么,重排会在哪些情况下发生?

页面初始化的时候;

操作DOM时,如添加或者删除可见的DOM元素;

元素位置改变;

元素的尺寸改变——边距、填充、边框、宽度和高度;

元素内容改变;(例如:一个文本被另一个不同尺寸的图片替代,用户在input框中输入文字)

浏览器窗口尺寸改变——resize事件发生时;

计算offsetWidth和offsetHeight属性;

设置style属性;

改变文字大小;

添加/删除样式表;

激活伪类,如:hover;

操作class属性;

这些都是显而易见的,或许你已经有过这样的体会,不间断地改变浏览器窗口大小,导致UI反应迟钝(某些低版本IE下甚至直接挂掉),现在你可能恍然大悟,没错,正是一次次的重排重绘导致的!

重排影响的范围:

触发重排时会对周围DOM重新排列,影响的范围有两种:

全局范围:从根节点html开始对整个渲染树进行重新布局。

局部范围:对渲染树的某部分或某一个渲染对象进行重新布局

2.引起重绘的情况

3.如何减少重排(Reflow)和重绘(Repaint)

重排和重绘是DOM编程中耗能的主要原因之一。

CSS中避免重排、重绘

避免设置多层内联样式;

尽可能在DOM树的最末端改变class;

动画效果应用到position属性为absolute或fixed的元素上;

避免使用table布局,table属性变化使用会直接导致布局重排或者重绘;(table及其内部元素除外,它可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花3倍于同等元素的时间。这也是为什么我们要避免使用table做布局的一个原因。)

不要在布局信息改变的时候做查询(会导致渲染队列强制刷新);

用translate替代top改变;

用opacity替代visibility(在独立图层下优化重绘)多用visibility:hidden少用display:none;

使用css3硬件加速,可以让transform、opacity、filters等动画效果不会引起回流重绘。

JS操作避免重排、重绘

减少直接操作dom元素,不要一条一条地修改DOM的样式,改用className用于控制;

不要把DOM结点的offsetLeft等属性值放在一个循环里当成循环里的变量;

如果需要创建多个DOM节点,可以使用DocumentFragment创建一个子树,之后一次性的拷贝到document;

先隐藏元素,进行修改后再显示该元素,因为display:none上的DOM操作不会引发回流和重绘;

对于复杂动画效果,使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流。

1
查看完整版本: CSS重排Reflow和重绘Repain