重绘 、回流
首先了解页面的呈现流程
- 浏览器把获取到的
HTML
代码解析成一个DOM
树,HTML
中的每个tag
都是DOM
树的1个节点,根节点就是document
对象(html tag
)。用firebug
或者IE Develop Toolbar
等工具可看到DOM
树,包括display:none
隐藏,还有js
动态添加的元素; - 浏览器把所有样式(主要包括
css
和浏览器的样式设置)解析成样式结构体。在解析过程中会去掉浏览器不能识别的样式,比如IE
会去掉-moz
开头的样式,Firefox
会去掉_
开头的样式; -
DOM tree
和样式结构体结合后构建呈现树(render tree
)。render tree
中每个node
都有自己的style
,而render tree
不包含隐藏的节点(比如display:none
的节点,还有head
节点),这些节点不会用于呈现,也不影响呈现,所以就不会包含在render tree
中。(visibility:hidden
隐藏的元素还会包含在render tree
中,因为会影响布局(layout
),会占有空间。根据CSS2
的标准,render tree
中的每个节点都称为box
(Box dimensions
),box
的所有属性:width,height,margin,padding,left,top,border等; -
render tree
构建完毕后,浏览器根据render tree
来绘制页面。
重绘与回流的特征
- 当
render tree
中的一些元素的外观、风格等不会影响布局的属性改变,比如bachground-color
,这就称为重绘。 - 当
render tree
中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重新构建,这就称为回流。每个页面在第一次加载的时候就回流了一次。
注:重绘不一定会引起回流,回流一定引起重绘。任何对render tree中元素的操作都会引起回流或重绘。
如何减少回流、重绘
- 当元素的几个样式同时改变时定义一个新的
className
,不要一个一个改变元素的样式属性; - 使用
documentfragment
或div
等元素进行缓存操作; - 先
display:none
隐藏元素,然后对元素进行所有操作,最后再显示该元素; - 不要经常访问会引起浏览器
flush
队列的属性,如果想要访问先读取到变量中进行缓存;
会引起浏览器flush
队列的属性:
offsetTop, offsetLeft, offsetWidth, offsetHeight
scrollTop/Left/Width/Height
clientTop/Left/Width/Height
width,height
请求了getComputedStyle(), 或者 ie的 currentStyle
- 让元素脱离动画流,减少回流的
render tree
的规模;
$("#block1").animate({left:50});
$("#block2").animate({marginLeft:50});
- 尽可能在
DOM
树的最末端改变class
(可限制回流的范围); - 避免设置多层内联样式(将样式合并在一个外部类,仅产生一次回流);
- 动画效果应用到
position
属性为absolute
或flex
的元素上; - 避免使用
table
数据; - 避免使用
CSS
的JavaScript
表达式。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。