在前面小节,我们对网页渲染过程做了介绍,其中最后两步就是layout与paint,当渲染对象被创建并添加到树中,它们并没有位置和大小,计算这些值的过程称为layout或reflow。绘制阶段,遍历渲染树并调用渲染对象的paint方法将它们的内容显示在屏幕上,绘制使用UI基础组件。

何时发生?

由两者的定义我们可以知道在元素的大小和位置发生变化时都会触发reflow,且也会引起repaint,当元素的位置和大小没有变化,如改变背景颜色等等,只会进行重新repaint,如修改opacity, background-color, visibility, outline等。

reflow比repaint开销更大,修改一个元素的大小或位置会影响它的子节点,父节点,兄弟节点甚至是整个文档。例如修改页面字体大小,将会导致整个文档reflow,在body最前面添加一个元素会导致后面所有元素reflow。

具体来说:

  • 添加、删除元素
  • 更改元素的display:none或显示引起reflow
  • 增加或删除元素style规则,不同规则影响不同,如修改width会引起reflow
  • 移动元素位置
  • CSS3动画,每一帧都会引起reflow(可能有硬件加速)
  • 用户行为如改变浏览器字体大小、改变窗口大小、在输入框输入文字、触发:hover等等

浏览器优化策略

  • 采用Dirty bit系统,只针对具有dirty标记的元素进行重新layout,即增量layout,且此过程是异步的.
  • Firefox为增量layout生成了reflow队列,以及一个调度执行这些批处理命令。Webkit也有一个计时器用来执行增量layout-遍历树,为dirty状态的渲染对象重新布局。意思是会将多个reflow操作汇集到一定数量后再一起处理,减轻压力
  • 如果元素只是位置发生变化,其大小从缓存里读取,就不用再次计算

针对上面的reflow队列,当访问以下style属性时,浏览器为了给你最精确的值,需要flush队列,因为队列中可能会有影响到这些值的操作:

  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop/Left/Width/Height
  • clientTop/Left/Width/Height
  • width,height
  • 请求了getComputedStyle(), 或者 ie的 currentStyle

减少reflow和repaint

布局技术最佳实践

  • 少使用内联样式
  • 表格数据使用:table-layout: fixed
  • flexbox布局可能带来性能问题

减少样式规则

许多时候我们在页面上引入的规则很多并没有用到,例如使用bootstrap等,除了按需引入外,我们还可以通过一些自动化工具去除页面中没有使用到的规则。如gulp-uncss:

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var uncss = require('postcss-uncss'); gulp.task('default', function () {
var plugins = [
uncss({
html: ['index.html', 'posts/**/*.html', 'http://example.com']
}),
];
return gulp.src('./src/*.css')
.pipe(postcss(plugins))
.pipe(gulp.dest('./dest'));
});

详情参考文档:https://github.com/ben-eb/gulp-uncss

减少DOM树嵌套层次

减少不必要的嵌套层可以加快reflow过程。

批量操作

如果以下面的方式更新元素:

var myelement = document.getElementById('myelement');
myelement.width = '100px';
myelement.height = '200px';
myelement.style.margin = '10px';

会造成三次reflow(不考虑浏览器优化)

改善方式是通过改变元素的class属性来应用样式表里不同规则:

var myelement = document.getElementById('myelement');
myelement.classList.add('newstyles');
.newstyles {
width: 100px;
height: 200px;
margin: 10px;
}

或者直接修改cssText:

myelement.cssText += 'width:100px;height:200px;margin:10px';

离线操作

  • 使用createDocumentFragment()等创建节点,再将其他所有节点加入其子节点,最后才加入到真实DOM里去
  • 先将元素设置为隐藏即:display:none,做一系列更改后再显示回来

减少访问会引起flush的属性

尽量减少访问上面提到的一系列会引起reflow队列flush的属性,如果要多次访问,最好设置缓存变量。

使进行复杂动画的元素脱离文档流

通过设置动画元素position: absolute; 或者 position: fixed;可以使元素脱离文档流来避免在动画的过程中影响其他元素。

// block1是position:absolute 定位的元素,它移动会影响到它父元素下的所有子元素。
// 因为在它移动过程中,所有子元素需要判断block1的z-index是否在自己的上面,
// 如果是在自己的上面,则需要重绘,这里不会引起回流
$("#block1").animate({left:50});
// block2是相对定位的元素,这个影响的元素与block1一样,但是因为block2非绝对定位
// 而且改变的是marginLeft属性,所以这里每次改变不但会影响重绘,
// 还会引起父元素及其下元素的回流
$("#block2").animate({marginLeft:50});

动画平滑度

动画每一帧元素移动1个像素和4个像素平滑程度比起来,两者平滑程度感受起来差别不大,但是后者会大大减少reflow次数。

动画硬件加速

// todo

参考

https://www.sitepoint.com/10-ways-minimize-reflows-improve-performance/

http://www.blogjava.net/BearRui/archive/2010/05/10/web_performance_repaint_relow.html

https://github.com/laoqiren/web-performance/blob/master/%E7%BD%91%E9%A1%B5%E6%B8%B2%E6%9F%93%E5%8E%9F%E7%90%86/repaint%E4%B8%8Ereflow.md

前段性能----repaint和reflow的更多相关文章

  1. javascript性能优化-repaint和reflow

    repaint(重绘) ,repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲 ...

  2. css的repaint和reflow

    css的repaint和reflow 浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构(geometries)的进程叫做 reflow. 由于 reflow 是一种浏览器中的用户拦截( ...

  3. 探讨css中repaint和reflow

    (个人blog迁移文章.) 前言: 页面设计中,不可避免的需要浏览器进行repaint和reflow.那到底什么是repaint和reflow呢.下面谈谈自己对repaint和reflow的理解,以及 ...

  4. [ JS 进阶 ] Repaint 、Reflow 的基本认识和优化

    你是不是经常听师兄或一些前端前辈说不能用CSS通配符 *,CSS选择器层叠不能超过三层,CSS尽量使用类选择器,书写HTML少使用table,结构要尽量简单-DOM树要小....等这些忠告,以前我就大 ...

  5. repaint和reflow的相关知识

    一个页面由两部分组成: DOM:描述该页面的结构 render渲染:描述 DOM 节点 (nodes) 在页面上如何呈现 repaint重绘: 当 DOM 元素的属性发生变化 (如 color) 时, ...

  6. 【转】javascript性能优化-repaint和reflow

    repaint(重绘) ,repaint发生更改时,元素的外观被改变,且在没有改变布局的情况下发生,如改变outline,visibility,background color,不会影响到dom结构渲 ...

  7. 性能优化之reflow和repaint

    本文主要介绍一下什么是reflow,repaint, 怎样避免它们造成的不良影响, 怎么通过工具查看分析它们. 一.首先对浏览器渲染引擎下网页呈现过程简要说一下: 浏览器的渲染引擎开始解析html构建 ...

  8. 前端性能优化-减少http请求,dns预解析,减少repaint和reflow

    前端性能优化方法: 一 . 减少http请求 (1)通过合并图片,减少请求,俗称css sprites(css精灵)css sprites (2)lazyload懒加载,在需要的时候再加载 1.定义: ...

  9. 前端性能优化--回流(reflow)和重绘(repaint)

    HTML加载时发生了什么 在页面加载时,浏览器把获取到的HTML代码解析成1个DOM树,DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等. 浏览器把所有样 ...

随机推荐

  1. GIT 安装和使用

    目录 GIT 安装和使用 一.GIT 介绍 二.GIT 安装 三.GIT 使用 1. 配置 2. 创建版本库 3. 远程仓库 4. 分支管理 5.标签管理 6. 自定义 GIT 安装和使用 一.GIT ...

  2. 【Python爬虫案例学习】Python爬取天涯论坛评论

    用到的包有requests - BeautSoup 我爬的是天涯论坛的财经论坛:'http://bbs.tianya.cn/list.jsp?item=develop' 它里面的其中的一个帖子的URL ...

  3. kubeadm初始化集群

    通过kubeadm创建集群本地测试非常方便,以下就简单记录下初始化需要的基本命令,环境准备这里不做说明 简单记录kubeadm初始化集群的基本命令 # 初始化集群 kubeadm init --kub ...

  4. 常用Java API之Ramdom--用代码模拟猜数小游戏

    常用Java API之Ramdom Ramdom类用来生成随机数字.使用起来也是三个步骤: 1.导包 import java.util.Random; 2.创建 Random r = new Rand ...

  5. Oracle查询所有字段另加两个拼接字段的操作

    Oracle查询所有字段,再加两个字段拼接, select a.*,(SNO||SNAME) from TEST_STUDENT a; 同理,查询所有字段,其中两个字段求和:(SNO和SAGE都是NU ...

  6. 3、Vue实例的属性

    1.获取Vue实例的属性 2.data属性 每个Vue实例都会代理其data对象里所有的属性.如果实例创建之后添加或者更改属性,他不会触发视图更新. 这句话说了下面两件事情 1.每个Vue实例都会代理 ...

  7. vant-ui rem问题

    使用vant-ui时rem单位问题 vue-cli3.x项目引入vant-ui1.6.21,要求在项目中使用rem单位,但vant是px的.故,需要添加一个自动转换插件和一段修改html根元素的fon ...

  8. 常用的本地存储-----cookie篇

    1.引言 随着浏览器的处理能力不断增强,越来越多的网站开始考虑将数据存储在「客户端」,那么久不得不谈本地存储了. 本地存储的好处: 一是避免取回数据前页面一片空白,如果不需要最新数据也可以减少向服务器 ...

  9. 模块化规范:CMD和AMD的区别

    https://www.zhihu.com/question/20351507/answer/14859415 AMD(异步模块定义) 是 RequireJS 在推广过程中对模块定义的规范化产出.CM ...

  10. css 带换行的垂直居中

    span{ display:flex; justify-content:left; align-items:center; height:100%; width:100%; }