- 2017年的老文,搬运存档用 -
有优化效果,但限制较多,X5 兼容 iOS 不行
layout
:防止元素内 layout 改变影响元素外,也防止其他元素改变影响这个元素。paint
:元素的子元素必须在元素的 content-box 中,不能超出,否则显示不出。子元素发生的任何改变都不会影响到与该元素之外的其他元素;同样该元素之外的其他元素都不会影响到子元素size
:用子元素是撑不开这个元素的(声明都不给它的尺寸会一直是 0x0),必须声明尺寸,且子元素不能超出元素的范围,这个属性能够阻止子元素不断变大 -> 改变父元素尺寸 -> 影响更多节点 -> 发成大面积重排。本身提供不了太大性能优化,一般是和 layout
搭配使用。style
:有些 CSS 属性会影响不只宿主元素和其子元素,比如 counter
。为了限制这样的属性影响到别的元素,让它的影响力限制在宿主元素和其子元素范围内。强行生成一棵 DOM 子树,变成像 shadow dom 那样的情况,外面的变量不会影响里面的;里面的也不会影响到外面。strict
:layout style paint sizecontent
:layout style paint注意:实验环境都是 macOS 10.12.6 Chrome stable 61。第三方插件和 cotainer queries 用得少,所以没研究。
If you build a off-screen navigation or similar, the browser paints the content completely although it is not visible on load. By setting
contain: paint;
the user agent can skip the paint off the off-screen element and therefore paint all the other content faster.
上文的意思是“如果构建一个屏幕外的导航栏(汉堡侧边栏),虽然看不到,但浏览器其实还会渲染那部分节点的。如果设置了 cotain: paint
那浏览器就不会去渲染屏幕外的东西,所以相对的屏幕内的内容就会被更快地渲染出来”。
为了验证这个理论,将用 FMP (first meaningful page) 和首次可操作时间 (First interactive) 作为主要的衡量标准,毕竟对于用户来说最有感知的应该也是这两个特性了。推理过程是这样的:
第一个页面:侧边栏有一个高斯模糊的图片,并动态加上了 1000 个高斯模糊的纯色点;通过改变 left
值实现的移入移出视口。(实验原则就是,怎么慢怎么来,满足了自己的破坏欲= =)
点击右上角「按钮」,控制侧边栏的移动:
多次实验后结果差不多是下面这样(Chrome devTools 的 Audits 面板):
二者的区别是在侧边栏上有无 contain: paint
。需要特别注意的是,添加了 contain: paint
相当于给元素加了一个 position:relative; overflow: clip
,所以子元素会相对这个父元素来定位了:
aside {
position: absolute;
z-index: 1;
top: 0;
bottom: 0;
left: -101%;
transition: left 500ms ease;
width: 80vw;
overflow: hidden; /* 为了和有 contain:paint 时的视觉效果一样*/
background-color: #414529;
background-image: url('http://qzonestyle.gtimg.cn/aoi/sola/20170707104843_SfolTLGT5s.jpg');
background-size: contain;
background-repeat: no-repeat;
filter: blur(10px);
contain: paint;
}
aside.open {
left: 0;
}
结论:FMP 和 First Interactive 都有优化,其中 FMP 优化了40ms。
内存使用情况如下图,这是多次试验以后取了效果对比最明显的:
case 2
按道理来说我们不应该看 FMP 而是应该看渲染的节点个数,但是因为侧边栏本身就是在复合层上,不参与 layout 时被影响的节点统计,通过开发者工具也没有检测到明显的效果(从上图中的 'layout' 可以看出)。所以写了另一个 demo,用来验证 Paul Lewis 文章中的效果:
实验内容就是,一个从上到下排列的页面结构,在中间颜色为黄色的节点内不断插入新的子节点,将会触发重排:
多次试验后的结果如下:
二者区别在于黄色节点有没有 contain: layout size
。另外 overflow: hidden
不会影响 layout root,但会影响 Nodes That Need Layout 这一栏。需要特别注意的是这两个属性值的使用场景,元素一定要有固定尺寸的。代码如下:
article {
position: relative;
z-index: 1;
background-color: #FFE32A;
/* no containment */
/* height: 200px;
* overflow: hidden;
*/
/* has containment */
height: 200px;
contain: layout size;
overflow: hidden;
}
结论是,在会引起重排的场景下,可以有效缩小重排的范围。
感谢 TBS 的同事,TBS 线上版本已经支持,也就是大安卓市场可以用起来了!但是 iOS…
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。