共计 1170 个字符,预计需要花费 3 分钟才能阅读完成。
简单先了解一下浏览器的渲染过程(图片来自于网络)
浏览器生成渲染树的过程(图片来自于网络)
回流
回流当 render tree 中的一部分或全部因为元素的规模尺寸、布局、隐藏等改变时,浏览器重新渲染部分 DOM 或全部 DOM 的过程。回流也被称为重排,其实从字面上来看,重排更容易让人形象易懂(即重新排版整个页面)。
重绘
当页面元素样式改变不影响元素在文档流中的位置时(如 background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作。
什么时候会触发回流或重绘?
有大量的用户行为以及潜在的 DHTML 改变会触发回流。例如,改变浏览器窗口的大小,使用一些 JavaScript 方法,包括计算样式,对 DOM 进行元素的添加或删除,或是改变元素的 class 等。
添加或者删除可见的 DOM 元素;
元素位置改变;
元素尺寸改变——边距、填充、边框、宽度和高度;
内容变化,比如用户在 input 框中输入文字,文本或者图片大小改变而引起的计算值宽度和高度改变;
页面渲染初始化;
浏览器窗口尺寸改变,resize 事件发生时;
计算 offsetWidth 和 offsetHeight 属性;
设置 style 属性的值;
回流必将引起重绘,而重绘不一定会引起回流。
如何减少回流、重绘?
一、CSS 中避免回流、重绘
1. 尽可能在 DOM 树的最末端改变 class2. 避免设置多层内联样式 3. 动画效果应用到 position 属性为 absolute 或 fixed 的元素上 4. 避免使用 table 布局 5. 使用 css3 硬件加速,可以让 transform、opacity、filters 等动画效果不会引起回流重绘
二、JS 操作避免回流、重绘
1. 避免使用 JS 一个样式修改完接着改下一个样式,最好一次性更改 CSS 样式,或者将样式列表定义为 class 的名称 2. 避免频繁操作 DOM,使用文档片段创建一个子树,然后再拷贝到文档中 3. 先隐藏元素,进行修改后再显示该元素,因为 display:none 上的 DOM 操作不会引发回流和重绘 4. 避免循环读取 offsetLeft 等属性,在循环之前把它们存起来 5. 对于复杂动画效果, 使用绝对定位让其脱离文档流,否则会引起父元素及后续元素大量的回流
总结:
回流在浏览器中属于一种用户主导的操作,所以知道如何去改进回流时间以及知道各种文档属性(DOM 节点深度,css 的渲染效率,各种各样的样式改变)对回流时间的影响对于前端开发来讲是很有帮助的。有时即便是回流一个单一的元素,也可能要求它的父元素以及任何跟随它的元素也产生回流。例如需要改变某个元素的背景,这就不涉及该元素的属性,所以只发生重绘。
写这篇文章,也看了很多相关的 blog 和文章,这篇文章写得不是很具体只是大概的内容。想深入了解的话可以看下面这篇文章,既有例子又有深度。你真的了解回流和重绘吗