浏览器 - 重绘(repaint)重排(reflow)
浏览器 - 重绘(repaint)重排(reflow)
网页生成过程:
- HTML被HTML解析器解析成DOM 树
- css则被css解析器解析成CSSOM 树
- 结合DOM树和CSSOM树,生成一棵渲染树(Render Tree)
- 生成布局(flow),即将所有渲染树的所有节点进行平面合成
- 将布局绘制(paint)在屏幕上
第四步和第五步是最耗时的部分,这两步合起来,就是我们通常所说的渲染。
渲染
网页生成的时候,至少会渲染一次。
在用户访问的过程中,还会不断重新渲染
重新渲染需要重复之前的第四步(重新生成布局)+第五步(重新绘制)或者只有第五个步(重新绘制)。
重排比重绘大:
大,在这个语境里的意思是:谁能影响谁?
- 重绘:某些元素的外观被改变,例如:元素的填充颜色
- 重排:重新生成布局,重新排列元素。
就如上面的概念一样,单单改变元素的外观,肯定不会引起网页重新生成布局,但当浏览器完成重排之后,将会重新绘制受到此次重排影响的部分。
比如改变元素高度,这个元素乃至周边dom都需要重新绘制。
也就是说:"重绘"不一定会出现"重排","重排"必然会出现"重绘"
重排(reflow)
概念
当DOM的变化影响了元素的几何信息(DOM对象的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排。
重排也叫回流,重排的过程以下面这种理解方式更清晰一些:
回流就好比向河里(文档流)扔了一块石头(dom变化),激起涟漪,然后引起周边水流受到波及,所以叫做回流
常见引起重排属性和方法
任何会改变元素几何信息(元素的位置和尺寸大小)的操作,都会触发重排,下面列一些栗子:
- 添加或者删除可见的DOM元素;
- 元素尺寸改变——边距、填充、边框、宽度和高度
- 内容变化,比如用户在input框中输入文字
- 浏览器窗口尺寸改变——resize事件发生时
- 计算 offsetWidth 和 offsetHeight 属性
- 设置 style 属性的值
width height margin padding
display border position overflow
clientWidth clientHeight clientTop clientLeft
offsetWudth offsetHeight offsetTop offsetLeft
scrollWidth scrollHeight scrollTop scrollLeft
scrollIntoView() scrollTo() getComputedStyle()
getBoundingClientRect() scrollIntoViewIfNeeded()
重排影响的范围
由于浏览器渲染界面是基于流失布局模型的,所以触发重排时会对周围DOM重新排列,影响的范围有两种:
- 全局范围:从根节点html开始对整个渲染树进行重新布局。
- 局部范围:对渲染树的某部分或某一个渲染对象进行重新布局
局部范围重排
用局部布局来解释这种现象:把一个dom的宽高之类的几何信息定死,然后在dom内部触发重排,就只会重新渲染该dom内部的元素,而不会影响到外界。
尽可能的减少重排的次数、重排范围:
重排需要更新渲染树,性能花销非常大:
它们的代价是高昂的,会破坏用户体验,并且让UI展示非常迟缓,我们需要尽可能的减少触发重排的次数。
重排的性能花销跟渲染树有多少节点需要重新构建有关系:
所以我们应该尽量以局部布局的形式组织html结构,尽可能小的影响重排的范围。
而不是像全局范围的示例代码一样一溜的堆砌标签,随便一个元素触发重排都会导致全局范围的重排。
重绘(Repaints)
概念
当一个元素的外观发生改变,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。
常见的引起重绘的属性
color border-style visibility background
text-decoration background-image background-position background-repeat
outline-color outline outline-style border-radius
outline-width box-shadow background-size
浏览器的渲染队列
eg:
思考以下代码将会触发几次渲染
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
根据我们上文的定义,这段代码理论上会触发4次重排+重绘,因为每一次都改变了元素的几何属性,实际上最后只触发了一次重排,这都得益于浏览器的渲染队列机制:
当我们修改了元素的几何属性,导致浏览器触发重排或重绘时。它会把该操作放进渲染队列,等到队列中的操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作。
- 强制刷新队列
div.style.left = '10px';
console.log(div.offsetLeft);
div.style.top = '10px';
console.log(div.offsetTop);
div.style.width = '20px';
console.log(div.offsetWidth);
div.style.height = '20px';
console.log(div.offsetHeight);
这段代码会触发4次重排+重绘,因为在console中你请求的这几个样式信息,无论何时浏览器都会立即执行渲染队列的任务,即使该值与你操作中修改的值没关联。
因为队列中,可能会有影响到这些值的操作,为了给我们最精确的值,浏览器会立即重排+重绘。
强制刷新队列的style样式请求:
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle(), 或者 IE的 currentStyle
我们在开发中,应该谨慎的使用这些style请求,注意上下文关系,避免一行代码一个重排,这对性能是个巨大的消耗
重排优化
分离读写操作
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
console.log(div.offsetLeft);
console.log(div.offsetTop);
console.log(div.offsetWidth);
console.log(div.offsetHeight);
还是上面触发4次重排+重绘的代码,这次只触发了一次重排:
在第一个console的时候,浏览器把之前上面四个写操作的渲染队列都给清空了。剩下的console,因为渲染队列本来就是空的,所以并没有触发重排,仅仅拿值而已。
样式集中改变
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';
虽然现在大部分浏览器有渲染队列优化,不排除有些浏览器以及老版本的浏览器效率仍然低下:
建议通过改变class或者csstext属性集中改变样式
// bad
var left = 10;
var top = 10;
el.style.left = left + "px";
el.style.top = top + "px";
// good
el.className += " theclassname";
// good
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
缓存布局信息
// bad 强制刷新 触发两次重排
div.style.left = div.offsetLeft + 1 + 'px';
div.style.top = div.offsetTop + 1 + 'px';
// good 缓存布局信息 相当于读写分离
var curLeft = div.offsetLeft;
var curTop = div.offsetTop;
div.style.left = curLeft + 1 + 'px';
div.style.top = curTop + 1 + 'px';
离线改变dom
- 隐藏要操作的dom
在要操作dom之前,通过display隐藏dom,当操作完成之后,才将元素的display属性为可见,因为不可见的元素不会触发重排和重绘。
dom.display = 'none'
// 修改dom样式
dom.display = 'block'
- 通过使用DocumentFragment创建一个dom碎片,在它上面批量操作dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
- 复制节点,在副本上工作,然后替换它!
position属性为absolute或fixed
position属性为absolute或fixed的元素,重排开销比较小,不用考虑它对其他元素的影响
优化动画
可以把动画效果应用到position属性为absolute或fixed的元素上,这样对其他元素影响较小
动画效果还应牺牲一些平滑,来换取速度,这中间的度自己衡量:启用GPPU加速
此部分来自优化CSS重排重绘与浏览器性能
GPU(图像加速器):
GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操作交给 GPU 来完成,因为 GPU 是专门为处理图形而设计,所以它在速度和能耗上更有效率。
GPU 加速通常包括以下几个部分:Canvas2D,布局合成, CSS3转换(transitions),CSS3 3D变换(transforms),WebGL和视频(video)。
/*
* 根据上面的结论
* 将 2d transform 换成 3d
* 就可以强制开启 GPU 加速
* 提高动画性能
*/
div {
transform: translate3d(10px, 10px, 0);
}
浏览器 - 重绘(repaint)重排(reflow)的更多相关文章
- 什么是回流(重排 reflow)?什么是重绘(repaint)?如何减少回流、重绘?
什么是回流(重排 reflow)? 回流(重排 reflow):对DOM树进行渲染,只要修改DOM或修改元素的形状大小,就会触发reflow,reflow的时候,浏览器会使已渲染好受到影响的部分失效, ...
- 页面重绘(repaint)和回流(reflow)
前言 页面显示到浏览器上的过程: 1.1.生成一个DOM树. 浏览器将获取到的HTML代码解析成1个DOM树,包含了所有标签,包括display:none和动态添加的节点. 1.2.生成样式结构体. ...
- 回流(reflow)与重绘(repaint)
回流(reflow)与重绘(repaint) 很早之前就听说过回流与重绘这两个名词,但是并不理解它们的含义,也没有深究过,今天看了一套网易的题目,涉及到了这两个概念,于是想要把它们俩弄清楚... 一. ...
- 浏览器渲染详细过程:重绘、重排和 composite 只是冰山一角
https://juejin.im/entry/590801780ce46300617c89b8 渲染 这张很经典的图许多人都看过,其中的概念大家应该都很熟悉,也就是这么几个步骤:js修改dom结构或 ...
- 关于重绘and重排
在研究CSS3动画性能的时候,看到了重排两个字. 突然想到自己虽然听说过这么个东东,但一直也没深入研究之. 趁着当下正好有研究的劲头,所以一不做二不休,把这个point也给学习了. 同样是一番查找资料 ...
- CSS新特性contain,控制页面的重绘与重排
在介绍新的 CSS 属性 contain 之前,读者首先需要了解什么是页面的重绘与重排. 之前已经描述过很多次了,还不太了解的可以先看看这个提高 CSS 动画性能的正确姿势. OK,下面进入本文正题, ...
- 浏览器的重绘与回流(Reflow & Repaint)介绍
重绘 当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作. 回流 当改变 ...
- 页面优化,谈谈重绘(repaint)和回流(reflow)
一.前言 偶尔在面试过程中遇到过重汇与回流reflow的问题,毕竟页面优化也是考核一个开发者能力的关键之一,上篇文章聊了下documentfragment也是为了减轻回流问题,那么本篇文章好好介绍下重 ...
- 前端性能优化--回流(reflow)和重绘(repaint)
HTML加载时发生了什么 在页面加载时,浏览器把获取到的HTML代码解析成1个DOM树,DOM树里包含了所有HTML标签,包括display:none隐藏,还有用JS动态添加的元素等. 浏览器把所有样 ...
- DOM的回流和重绘(重排、重绘)
什么是DOM回流? 页面渲染时,我们对HTML结构简单的增删查改时,浏览器会对所有的dom进行重新排序,这就i是DOM回流,严重影响浏览器性能 DOM的回流和重绘: **DOM的回流**:当页面中元素 ...
随机推荐
- day01-Spring基本介绍
Spring基本介绍 1.官方资料和下载 1.1Spring5下载 直接访问 https://repo.spring.io/ui/native/release/org/springframework/ ...
- do-while循环-练习_用循环求出1-100之间的耦合数
do-while循环 do..while循环格式 初始化表达式① do{ 循环体③ 步进表达式④ }while(布尔表达式②); 执行流程 执行顺序:①③④>②③④>②③④-②不满足为止. ...
- 【译】使用 ML.NET 进行机器学习 - 集群完整指南
原文 | Nikola M. Zivkovic 翻译 | 郑子铭 在之前的几篇文章中,我们探索了一些基本的机器学习算法.到目前为止,我们介绍了一些简单的回归算法,分类 算法.我们使用 ML.NET 实 ...
- nodejs 环境变量配置
1.下载 下载地址: https://nodejs.org/zh-cn/download/ 2.安装 安装一直下一步即可,建议安装路径不要包含中文 3.环境变量配置 1)右键[我的电脑],点击[属性] ...
- STM32F0_HAL初始化系列:FLASH写入
//读 read_temp = *(__IO uint32_t*)value_address; //写 static void flash_write(uint32_t address, uint32 ...
- python requests 最牛攻略
目录 安装 Reuqests HTTP 简介 什么是 HTTP HTTP工作原理 HTTP的9种请求方法 HTTP状态码 requests 快速上手 requests 发起请求的步骤 requests ...
- Redis 源码解读之逐出策略
Redis 源码解读之逐出策略 背景和问题 本文想解决的问题: redis 触发逐出的时机是怎样的? redis 逐出策略有哪些? 如何在海量的 key 中快速找到逐出评价值(idle)最高的key, ...
- JZOJ 1078. 【GDOI2006】The Kth Element
\(\text{Problem}\) 给定一个整数序列 \(a[1..N]\),定义 \(sum[i][j]=a[i]+a[i+1]+...+a[j]\),将所有的 \(sum[i][j]\) 从小到 ...
- C语言初学习
首先我们先看一下什么是编译型语言和解释型语言: 解释:借助一个程序,那个程序能试图理解你的程序,然后按照你的要求执行 编译:借助一个程序,就像一个翻译,把你的程序翻译成计算机真正能懂得语言--机器语言 ...
- CCRD_TOC_2008年第11期
中信国健临床通讯 2008年第11期(总第24期) 目 录 脊柱关节炎 1. 一项多中心.大型.随机.双盲.对照试验证实依那西普治疗AS的疗效优于柳氮磺吡啶 Braun J, et al. ACR ...