【面试题】有关css 重排和重绘详解

一、前言

面试的时候经常被问到,css重排(Reflow)和重绘(Repaint)。从字面意思也可以理解重排是重新排列,重绘是重新,绘制。

二、相关概念

在了解Reflow和Repaint 之前我们需要了解以下几个概念。

2.1 Dom Tree

在讲解dom tree 之前应该了解一下什么是dom?
DOM 全称是 Document Object Model,
译为文档对象模型。请注意里面的对象两字。

每个HTML标签都是一个对象,嵌套的标签是闭合的子标签。
DOM 由此可以将一段HTML 代码表示为标签的树型结构。只要内容在html中就会加入到dom tree 中,包括注释。

每一个树的节点都是一个对象

  1. document — DOM 的“入口点”。
  2. 标签节点
  3. 元素内的文本形成文本节点 标记为#text
    一个文本节点只包含一个字符串,没有节点,是树的叶子
    a. 特殊字符(,<head> 之前的空格和换行符均被忽略。)
    1.特殊字符↵ (js 中为\n)
    2.空格␣
  4. 注释节点类型(不会显示在dom中但是,js可以从dom中读取到)
    示例:
<!DOCTYPE HTML> 
<html> 
<head> 
	<title>About elk</title> 
</head> 
<body>
	The truth about elk. 
</body> 
</html>

dom树结构
Dom 树结构

2.2 Render Tree

在了解了Dom Tree 之后,我们就可以进阶一步了解Render Tree。

dom节点:

  1. 可视化节点(div p 等这种结构性标签)
  2. 非可视化节点(script meta 等在这种页面上显示不出来的节点)

浏览器获取 HTML 文件,然后对文件进行解析,形成DOM Tree

与此同时,进行 CSS 解析,生成 Style Rules

接着将 DOM Tree 与 Style Rules 合成为 Render Tree

元素在页面中布局,然后绘制

render 树就是根据 可视化节点 和 css 样式表 结合诞生出来的树;

注意:PS: display: none 的元素会出现在 DOM树 中,但不会出现在 render 树中;

三、什么是Reflow?

当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。

引起回流的操作

  1. 页面首次渲染
  2. 浏览器窗口大小发生改变
  3. 元素尺寸或位置发生改变
  4. 元素内容变化(文字数量或图片大小等等)
  5. 元素字体大小变化
  6. 添加或者删除可见DOM元素
  7. 激活CSS伪类(例如::hover
  8. 查询某些属性或调用某些方法

一些常用且会导致回流的属性和方法:

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

四、什么是Repaint?

当页面中元素样式的改变并不影响它在文档流中的位置时(例如:colorbackground-colorvisibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。

当一个元素的外观发生改变的时候,但是并不改变布局,重新绘制元素的过程,叫做重绘。比如color,background-color,visibility等相关元素背景,文字颜色,边框样式

五、重排和重绘的影响

在了解了回流和重绘的时候,我们可以得出。回流比重绘的代价要更高。

因为每次在回流操作中,都需要生成一次Render Tree。

现代浏览器会对频繁的回流或重绘操作进行优化:

浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。

六、如何针对回流和重绘进行优化

6.1 css 方面

  1. 避免使用table布局
  2. 尽可能在dom树最末端改变class
  3. 将动画效果应用到position属性为absolute或者fixed的元素上。(如果需要重排,尽量做局部重拍,不影响其他元素)
  4. 避免使用css表达式 比如calc()

有关第三点,其实就是分层,将全局重排变为局部重排,但是会有

绘制可以将布局树中的元素分解为多个层。将内容提升到 GPU 上的层(而不是 CPU 上的主线程)可以提高绘制和重新绘制性能。有一些特定的属性和元素可以实例化一个层,包括 <video><canvas>,任何 CSS 属性为 opacity 、3D transformwill-change 的元素,还有一些其他元素。这些节点将与子节点一起绘制到它们自己的层上,除非子节点由于上述一个(或多个)原因需要自己的层。
分层确实可以提高性能,但是它以内存管理为代价,因此不应作为 web 性能优化策略的一部分过度使用。

6.2 js 方面

  1. 多个样式更改最好用一个calss去更改,
  2. 避免重复操作dom。可以将dom操作定义到一个变量中。最后添加到文本中
  3. 可以对元素初始属性设置display: none , 对dom操作结束再让其显示出来。因为修改display:none ,不会引起dom的重排和重绘制

七、总结

7.1 浏览器渲染

浏览器获取 HTML 文件,然后对文件进行解析,形成 [[DOM Tree]]

与此同时,进行 CSS 解析,生成 Style Rules

接着将 DOM Tree 与 Style Rules 合成为 Render Tree

元素在页面中布局,然后绘制

render 树就是根据 可视化节点 和 css 样式表 结合诞生出来的树;

7.2 重排必定重绘,重绘不一定重排。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值