css样式优先级
- 内联样式 > ID选择器 > 类选择器 > 标签选择器 > 通用选择器 > 继承样式 > 浏览器默认样式
重排和重绘
- 当我们的操作引发了 DOM 树中几何尺寸的变化(改变元素的大小、位置、布局方式等),这时渲染树里有改动的节点和它影响的节点都要重新计算。这个过程就叫做重排,也称为回流。在改动发生时,要重新经历页面渲染的整个流程,所以开销是很大的。
重排
以下操作都会导致页面重排:
- 页面首次渲染;
- 浏览器窗口大小发生变化;
- 元素的内容发生变化;
- 元素的尺寸或者位置发生变化;
- 元素的字体大小发生变化;
- 激活CSS伪类;
- 查询某些属性或者调用某些方法;
- 添加或者删除可见的DOM元素。
在触发重排时,由于浏览器渲染页面是基于流式布局的,所以当触发回流时,会导致周围的DOM元素重新排列,它的影响范围有两种:
- 全局范围:从根节点开始,对整个渲染树进行重新布局;
- 局部范围:对渲染树的某部分或者一个渲染对象进行重新布局。
重绘
当对 DOM 的修改导致了样式的变化、但未影响其几何属性(比如修改颜色、背景色)时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式(会跳过重排环节),这个过程叫做重绘。简单来说,重绘是由对元素绘制属性的修改引发的。
当我们修改元素绘制属性时,页面布局阶段不会执行,因为并没有引起几何位置的变换,所以就直接进入了绘制阶段,然后执行之后的一系列子阶段。相较于重排操作,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。
下面这些属性会导致回流:
- color、background 相关属性:background-color、background-image 等;
- outline 相关属性:outline-color、outline-width 、text-decoration;
- border-radius、visibility、box-shadow。
注意: 当触发重排时,一定会触发重绘,但是重绘不一定会引发重排。
相对来说,重排操作的消耗会比较大,所以在操作中尽量少的造成页面的重排。为了减少重排,可以通过以下方式进行优化:
- 在条件允许的情况下尽量使用 CSS3 动画,它可以调用 GPU 执行渲染。
- 操作DOM时,尽量在低层级的DOM节点进行操作
- 不要使用
table布局, 一个小的改动可能会使整个table进行重新布局 - 使用CSS的表达式
- 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式。
- 使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
- 避免频繁操作DOM,可以创建一个文档片段
documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中 - 将元素先设置
display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。 - 将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写。这得益于浏览器的渲染队列机制。
浏览器针对页面的回流与重绘,进行了自身的优化——渲染队列, 浏览器会将所有的回流、重绘的操作放在一个队列中,当队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会对队列进行批处理。这样就会让多次的回流、重绘变成一次回流重绘
以下操作尽量避免触发重排
- 改变 DOM 元素的几何属性:比如盒模型相关的 width、height、padding、margin、border,位置信息 left、top 等
- 改变 DOM 树结构:比如对 DOM 节点的增减、移动等操作
- 获取一些计算属性的值:比如偏移量,滚动量,窗口等计算属性值,offsetTop、scrollTop、 clientWidth 等