3、探究CSS和JS阻塞问题( 二 )


回流一定会引起重绘,但重绘不一定引起回流 。回流无法避免,且对性能影响很大 。目前流行的一些效果,如树状目录的折叠/展开、鼠标滑过、点击等,只要这些操作引起页面上某些元素的占位面积、定位方式、边界等属性变化,都会引起目标元素内部、周围甚至整个页面的回流和重新渲染 。
注意1::none的节点不会被挂载到渲染树,而:会被加入 。所以若某个节点最开始不显示,设置为:none是更好的选择 。使用显示和隐藏节点时会触发回流,而使用只会触发重绘,因为位置和尺寸没有变化 。
注意2:浏览器对回流和重绘是有优化策略的,有些情况下,例如修改了元素的样式,浏览器是不会立即执行重绘或回流的,而是把操作放进渲染队列中攒着,达到一定量级或时间后,统一处理 。但有些情况,会引起浏览器提前清空渲染队列,因为只有清空队列才能计算出最新的元素尺寸和位置样式信息,已确保特定的属性和方法可以获取到正确的数据,例如窗口、改变页面默认字体等,浏览器会马上执行回流 。
哪些操作会触发回流
1、浏览器窗口大小发生变化2、元素尺寸或位置发生变化3、元素内容发生变化4、字体大小发生变化5、添加或删除可见的DOM元素6、激活CSS伪类,例如:hover7、查询某些属性或调用某些方法
哪些属性和方法可以引起回流
如下所有的属性和方法,在读取或执行的同时,会立即触发回流,清空渲染队列 。
【1、元素类】【1.1元素测量】elem.offsetLeft,elem.offsetTop,elem.offsetWidth,elem.offsetHeight,elem.offsetParentelem.clientLeft,elem.clientTop,elem.clientWidth,elem.clientHeightelem.getClientRects(),elem.getBoundingClientRect()【1.2滚动相关】elem.scrollBy(),elem.scrollTo()elem.scrollIntoView(),elem.scrollIntoViewIfNeeded()elem.scrollWidth,elem.scrollHeightelem.scrollLeft,elem.scrollTop 除了读取,设置也会触发【1.3聚焦】elem.focus() 会触发两次强制布局【1.4其他】elem.computedRole,elem.computedNameelem.innerText【2、getComputedStyle】概念:getComputedStyle调用通常会导致样式重新计算,且当满足下列条件时,会触发强制布局【2.1出现下列任意一个媒体查询时】(1)min-width,min-height,max-width,max-height,width,height(2)aspect-ratio,min-aspect-ratio,max-aspect-ratio(3)device-pixel-ratio,resolution,orientation,min-device-pixel-ratio,max-device-pixel-ratio【2.2所获取的属性是下列之一时】(1)height,width(2)top,right,bottom,left(3)margin [-top, -right, -bottom, -left, 或简写形式] 仅在数值是定值时(4)padding [-top, -right, -bottom, -left, 或简写形式] 仅在数值是定值时(5)transform, transform-origin, perspective-origin(6)translate, rotate, scale(7)grid, grid-template, grid-template-columns, grid-template-rows(8)perspective-origin【3、window】window.scrollX,window.scrollYwindow.innerHeight,window.innerWidthwindow.getMatchedCSSRules() 仅会导致样式重新计算【4、表单】inputElem.focus()inputElem.select(),textareaElem.select()【5、鼠标事件】mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY【6、document】doc.scrollingElement 仅会导致样式重新计算【7、Range】range.getClientRects(), range.getBoundingClientRect()
优化措施:CSS侧如何避免回流
1、避免使用table布局,该布局通常需要多次计算,花费时间倍数于同等元素2、尽可能在DOM树的最末端改变class,减少回流的范围3、避免设置多层内联样式4、将动画效果应用到absolute或fixed元素上,使之脱离文档流5、避免使用CSS表达式,例如calc()6、开启CSS3硬件加速1)可以让transform、opacity、filter不会引起回流重绘2)尽量使用CSS3的transform来代替top\left等操作7、为动画元素新建图层,提高动画元素的z-index