1. 浏览器渲染机制

  • 浏览器采用流式布局模型(Flow Based Layout
  • 浏览器会把HTML解析成DOM,把CSS解析成CSSOMDOMCSSOM合并就产生了渲染树(Render Tree)。
  • 有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
  • 由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。

2. 重绘

由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outlinevisibilitycolorbackground-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。

3. 回流

回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。

<body>
<div class="error">
<h4>我的组件</h4>
<p><strong>错误:</strong>错误的描述…</p>
<h5>错误纠正</h5>
<ol>
<li>第一步</li>
<li>第二步</li>
</ol>
</div>
</body>

在上面的HTML片段中,对该段落(<p>标签)回流将会引发强烈的回流,因为它是一个子节点。这也导致了祖先的回流(div.errorbody – 视浏览器而定)。此外,<h5><ol>也会有简单的回流,因为其在DOM中在回流元素之后。大部分的回流将导致页面的重新渲染。

回流必定会发生重绘,重绘不一定会引发回流。

4. 浏览器优化

现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。

主要包括以下属性或方法:

  • offsetTopoffsetLeftoffsetWidthoffsetHeight
  • scrollTopscrollLeftscrollWidthscrollHeight
  • clientTopclientLeftclientWidthclientHeight
  • widthheight
  • getComputedStyle()
  • getBoundingClientRect()

所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。

5. 减少重绘与回流

  1. CSS

    • 使用 transform 替代 top

    • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局

    • 避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。

    • 尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。

    • 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。

      <div>
      <a> <span></span> </a>
      </div>
      <style>
      span {
      color: red;
      }
      div > a > span {
      color: red;
      }
      </style>

      对于第一种设置样式的方式来说,浏览器只需要找到页面中所有的 span 标签然后设置颜色,但是对于第二种设置样式的方式来说,浏览器首先需要找到所有的 span 标签,然后找到 span 标签上的 a 标签,最后再去找到 div 标签,然后给符合这种条件的 span 标签设置颜色,这样的递归过程就很复杂。所以我们应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。

    • 将动画效果应用到position属性为absolutefixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame

    • 避免使用CSS表达式,可能会引发回流。

    • 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-changevideoiframe等标签,浏览器会自动将该节点变为图层。

    • CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transformopacityfilters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

  2. JavaScript

    • 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
    • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
    • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
    • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。

介绍下重绘和回流(Repaint & Reflow),以及如何进行优化的更多相关文章

  1. 重绘和回流(reflow和repaint)

    由于DOM操作会导致浏览器的回流,回流需要花费大量的时间进行样式计算和节点重绘与渲染,所以应当尽量减少回流次数. 以下是几种常见的减少重绘和回流的方法: 一.不要一项一项的更改页面的样式,尽量一口气写 ...

  2. DOM的重绘和回流及代码性能优化

    1.DOM的重绘和回流Repaint&Reflow 1.1重绘:元素样式的改变(但宽高.大小.位置等不变) 如outline.visibility.color.background-color ...

  3. 理解浏览器的重绘与回流(repaint&&reflow)

    今天在做练习的时候,遇到了重绘与回流这个词,表示连个毛都没有听过.遂查之,首先将网上的(http://blog.sina.com.cn/s/blog_8dace7290102wezv.html)关于这 ...

  4. 重绘和回流(Repaint & Reflow)总结,以及如何进行优化

    1. 浏览器渲染机制 浏览器采用流式布局模型(Flow Based Layout) 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tre ...

  5. 浅谈JS重绘与回流

    在说浏览器渲染页面之前,我们需要先了解两个点,一个叫 浏览器解析 URL,另一个就是本章节将涉及的 重绘与回流: 重绘(repaint):当元素样式的改变不影响布局时,浏览器将使用重绘对元素进行更新, ...

  6. 【web性能】页面呈现、重绘、回流

    在讨论页面重绘.回流之前.需要对页面的呈现流程有些了解,页面是怎么把html结合css等显示到浏览器上的,下面的流程图显示了浏览器对页面的呈现的处理流程.可能不同的浏览器略微会有些不同.但基本上都是类 ...

  7. Qt重绘之update,repaint详解

    Qt里面的重绘和Windows编程里面的重绘差不多.但是Qt的重绘更有特色,更加智能. 在讲之前,先说说paintEvent() paintEvent()是一个虚函数槽(slot),子类可以对父类的p ...

  8. 高性能WEB开发:深入理解页面呈现、重绘、回流

    在讨论页面重绘.回流之前.需要对页面的呈现流程有些了解,页面是怎么把html结合css等显示到浏览器上的,下面的流程图显示了浏览器对页面的呈现的处理流程.可能不同的浏览器略微会有些不同.但基本上都是类 ...

  9. Web前端性能优化-重绘与回流

    1.什么是重绘与回流 Render tree 的重新构建就叫回流.当布局和几何属性改变时就需要回流,鼠标移动到图片 图片变大 也会触发回流.回流 能避免就避免 Render tree 改变外观.风格 ...

随机推荐

  1. error: RPC failed; curl 18 transfer closed with outstanding read data remaining的解决

    解决方案也是网上搜的,总结一下 一,加大缓存区git config --global http.postBuffer 524288000这个大约是500M二.少clone一些,–depth 1git ...

  2. phpstorm里面无法配置deployment?

    我的preference里面找不到deployment是什么回事啊? 解决方案: 导致这个问题的原因是PHPStorm的plugins里面没有Remote Hosts Access这个插件,安装一下这 ...

  3. [51nod 1847]奇怪的数学题

    [ 51nod 1847 ]奇怪的数学题 题目   点这里看题目. 分析   是挺奇怪的......   以下定义质数集合为\(P\),\(p_i\)为第\(i\)个质数.   定义\(mp(x)\) ...

  4. 给博客使用Butterfly主题并部署到GitHub服务器

    目录 前言 一.安装Butterfly主题 二.将本地博客部署到GitHub服务器 三.将个人域名与GitHub绑定 前言 安装完Hexo框架后,自带的主题在thems文件夹下可以查看,应用后界面: ...

  5. CKA考试个人心得分享

    考试相关准备: 真题:需要的私密: 网络:必须开启VPN,以便能访问国外网络,强烈建议在香港搭建相应FQ: 证件:考试需要出示含有拉丁文(英文)带照片的有效证件,相关有效证件参考(优先建议护照):ht ...

  6. 如何从二进制文件中读取int型序列

    使用的主要函数是int.from_bytes 代码如下: f = open('./T26.dat', 'rb') for i in range(20): A = f.read(2) A = int.f ...

  7. css3动画特效代码

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. centos7搭建EFK

    环境: system: CentOS Linux release 7.7.1908 elasticsearch: elasticsearch-7.5.1-1.x86_64 kibana: kibana ...

  9. 【JMeter_10】JMeter逻辑控制器__ForEach控制器<ForEach Controller>

    ForEach控制器<ForEach Controller> 业务逻辑: ForEach控制器一般与用户自定义变量/JDBC结果变量一起使用,可以认为他就是一种遍历型循环,该节点下的脚本内 ...

  10. rust 神奇的特质

    pub trait Summary { fn summarize_author(&self) -> String; fn summarize(&self) -> Strin ...