CSS 新特性 contain控制页面的重绘与重排问题


Posted in HTML / CSS onApril 30, 2021

CSS 新特性 contain控制页面的重绘与重排问题

在介绍新的 CSS 属性 contain 之前,需要读者已经知道什么是页面的重绘与重排。

发现之前已经描述过很多次了,可以看看这个提高 CSS 动画性能的正确姿势[1]。

OK,下面进入本文正题,

contain 为何?

contain 属性允许我们指定特定的 DOM 元素和它的子元素,让它们能够独立于整个 DOM 树结构之外。目的是能够让浏览器有能力只对部分元素进行重绘、重排,而不必每次都针对整个页面。

The contain property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a pmited area of the DOM and not the entire page.contain 语法

看看它的语法:

{ 
  /* No layout containment. */ 
  contain: none; 
  /* Turn on containment for layout, style, paint, and size. */ 
  contain: strict; 
  /* Turn on containment for layout, style, and paint. */ 
  contain: content; 
  /* Turn on size containment for an element. */ 
  contain: size; 
  /* Turn on layout containment for an element. */ 
  contain: layout; 
  /* Turn on style containment for an element. */ 
  contain: style; 
  /* Turn on paint containment for an element. */ 
  contain: paint; 
}

 

除去 none,取值还有 6 个,我们一个一个来看看。

contain: size

contain: size: 设定了 contain: size 的元素的渲染不会受到其子元素内容的影响。

The value turns on size containment for the element. This ensures that the containing box can be laid out without needing to examine its descendants.

我开始看到这个定义也是一头雾水,光看定义很难明白到底是什么意思。还需实践一番:

假设我们有如下简单结构:

<div class="container"> 
    
</div>
.container { 
    width: 300px; 
    padding: 10px; 
    border: 1px solid red; 
} 
 
p { 
    border: 1px solid #333; 
    margin: 5px; 
    font-size: 14px; 
}

并且,借助 jQuery 实现每次点击容器添加一个 <p>Coco</p> 结构:

$('.container').on('click', e => { 
    $('.container').append('<p>Coco</p>') 
})

 

那么会得到如下结果:

CSS 新特性 contain控制页面的重绘与重排问题

可以看到,容器 .container 的高度是会随着元素的增加而增加的,这是正常的现象。

此刻,我们给容器 .container 添加一个 contain: size,也就会出现上述说的:设定了 contain: size 的元素的渲染不会受到其子元素内容的影响。

.container { 
    width: 300px; 
    padding: 10px; 
    border: 1px solid red; 
+   contain: size 
}

再看看会发生什么:

CSS 新特性 contain控制页面的重绘与重排问题

正常而言,父元素的高度会因为子元素的增多而被撑高,而现在,子元素的变化不再影响父元素的样式布局,这就是 contain: size 的作用。

contain: style

接下来再说说 contain: style、contain: layout 、contain: paint。先看看 contain: style。

截止至本文书写的过程中,contain: style 暂时被移除了。

CSS Containment Module Level 1[2]: Drop the at-risk “style containment” feature from this specification, move it Level 2。

嗯,官方说辞是因为存在某些风险,暂时被移除,可能在规范的第二版会重新定义吧,那这个属性也暂且放一放。

contain: paint

contain: paint:设定了 contain: paint 的元素即是设定了布局限制,也就是说告知 User Agent,此元素的子元素不会在此元素的边界之外被展示,因此,如果元素不在屏幕上或以其他方式设定为不可见,则还可以保证其后代不可见不被渲染。

This value turns on paint containment for the element. This ensures that the descendants of the containing box don’t display outside its bounds, so if an element is off-screen or otherwise not visible, its descendants are also guaranteed to be not visible.

这个稍微好理解一点,先来看第一个特性:

设定了 contain: paint 的元素的子元素不会在此元素的边界之外被展示 设定了 contain: paint 的元素的子元素不会在此元素的边界之外被展示

这个特点有点类似与 overflow: hidden,也就是明确告知用户代理,子元素的内容不会超出元素的边界,所以超出部分无需渲染。

简单示例,假设元素结构如下:

<div class="container"> 
    <p>Coco</p> 
</div>
.container { 
    contain: paint; 
    border: 1px solid red; 
} 
 
p{ 
    left: -100px; 
}

我们来看看,设定了 contain: paint 与没设定时会发生什么:

CSS 新特性 contain控制页面的重绘与重排问题

CodePen Demo -- contain: paint Demo[3]

设定了 contain: paint 的元素在屏幕之外时不会渲染绘制

通过使用 contain: paint, 如果元素处于屏幕外,那么用户代理就会忽略渲染这些元素,从而能更快的渲染其它内容。

contain: layout

contain: layout:设定了 contain: layout 的元素即是设定了布局限制,也就是说告知 User Agent,此元素内部的样式变化不会引起元素外部的样式变化,反之亦然。

This value turns on layout containment for the element. This ensures that the containing box is totally opaque for layout purposes; nothing outside can affect its internal layout, and vice versa.

启用 contain: layout 可以潜在地将每一帧需要渲染的元素数量减少到少数,而不是重新渲染整个文档,从而为浏览器节省了大量不必要的工作,并显着提高了性能。

使用 contain:layout,开发人员可以指定对该元素任何后代的任何更改都不会影响任何外部元素的布局,反之亦然。

因此,浏览器仅计算内部元素的位置(如果对其进行了修改),而其余DOM保持不变。因此,这意味着帧渲染管道中的布局过程将加快。

存在的问题

描述很美好,但是在实际 Demo 测试的过程中(截止至2021/04/27,Chrome 90.0.4430.85),仅仅单独使用 contain:layout 并没有验证得到上述那么美好的结果。

设定了 contain: layout 的指定元素,改元素的任何后代的任何更改还是会影响任何外部元素的布局,点击红框会增加一条<p>Coco<p>元素插入到 container 中:

简单的代码如下:

<div class="container"> 
    <p>Coco</p> 
    ... 
</div> 
<div class="g-test"></div>
html, 
body { 
    width: 100%; 
    height: 100%; 
    display: flex; 
    justify-content: center; 
    align-items: center; 
    flex-direction: column; 
    gap: 10px; 
} 
 
.container { 
    width: 150px; 
    padding: 10px; 
    contain: layout; 
    border: 1px solid red; 
} 
 
.g-test { 
    width: 150px; 
    height: 150px; 
    border: 1px solid green; 
}

CSS 新特性 contain控制页面的重绘与重排问题

CodePen Demo -- contain: layout Demo[4]

Can i Use -- CSS Contain

截止至 2021-04-27,Can i Use 上的 CSS Contain 兼容性,已经可以开始使用起来:

CSS 新特性 contain控制页面的重绘与重排问题

参考文献

CSS Containment Module Level 1[5]

CSS containment[6]

CSS Containment in Chrome 52[7]

参考资料

[1]提高 CSS 动画性能的正确姿势:

https://github.com/chokcoco/iCSS/issues/11

[2]CSS Containment Module Level 1:

https://www.w3.org/TR/css-contain-1/

[3]CodePen Demo -- contain: paint Demo:

https://codepen.io/Chokcoco/pen/KKwmgmN

[4]CodePen Demo -- contain: layout Demo:

https://codepen.io/Chokcoco/pen/rNjRELL

[5]CSS Containment Module Level 1:

https://www.w3.org/TR/css-contain-1/

[6]CSS containment:

https://justmarkup.com/articles/2016-04-05-css-containment/

[7]CSS Containment in Chrome 52:

https://developers.google.com/web/updates/2016/06/css-containment

[8]Github -- iCSS:

https://github.com/chokcoco/iCSS

到此这篇关于CSS 新特性 contain控制页面的重绘与重排的文章就介绍到这了,更多相关CSS 控制页面的重绘与重排内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

HTML / CSS 相关文章推荐
利用CSS3实现毛玻璃效果示例源码
Sep 25 HTML / CSS
CSS3地图动态实例代码(圆圈向外扩散)
Jun 15 HTML / CSS
css3动画过渡实现鼠标跟随导航效果
Feb 08 HTML / CSS
CSS3 Notes: -webkit-box-reflect实现倒影的实例
Dec 08 HTML / CSS
html5 canvas 画图教程案例分析
Nov 23 HTML / CSS
HTML5使用ApplicationCache接口实现离线缓存技术解决离线难题
Dec 13 HTML / CSS
HTML5 Video/Audio播放本地文件示例介绍
Nov 18 HTML / CSS
canvas 橡皮筋式线条绘图应用方法
Feb 13 HTML / CSS
JavaScript+Canvas实现自定义画板的示例代码
May 13 HTML / CSS
HTML5 drag和drop具体使用详解
Jan 18 HTML / CSS
HTML5中 rem适配方案与 viewport 适配问题详解
Apr 27 HTML / CSS
css3属性选择器 “~”(波浪号) “,”(逗号) “+”(加号)和 “>”(大于号)
Apr 19 HTML / CSS
CSS3新特性详解(五):多列columns column-count和flex布局
css position fixed 左右双定位的实现代码
Apr 29 #HTML / CSS
css3 利用transform-origin 实现圆点分布在大圆上布局及旋转特效
CSS3实现的侧滑菜单
CSS完成视差滚动效果
Html5通过数据流方式播放视频的实现
Apr 27 #HTML / CSS
CSS3实现的3D隧道效果
You might like
php.ini 中文版
2006/10/28 PHP
PHP最常用的2种设计模式工厂模式和单例模式介绍
2012/08/14 PHP
使用php将某个目录下面的所有文件罗列出来的方法详解
2013/06/21 PHP
php一个解析字符串排列数组的方法
2015/05/12 PHP
Zend Framework框架教程之Zend_Db_Table_Rowset用法实例分析
2016/03/21 PHP
javascript 写类方式之二
2009/07/05 Javascript
js截取函数(indexOf,join等)
2010/09/01 Javascript
jquery模拟SELECT下拉框取值效果
2013/10/23 Javascript
用javascript添加控件自定义属性解析
2013/11/25 Javascript
JavaScript实现点击按钮切换网页背景色的方法
2015/10/17 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
jquery分页插件jquery.pagination.js实现无刷新分页
2016/04/01 Javascript
浅谈javascript的url参数parse和build函数
2017/03/04 Javascript
让div运动起来 js实现缓动效果
2017/07/06 Javascript
Angular.js前台传list数组由后台spring MVC接收数组示例代码
2017/07/31 Javascript
详解vue 动态加载并注册组件且通过 render动态创建该组件
2019/05/30 Javascript
layui导出所有数据的例子
2019/09/10 Javascript
微信小程序实用代码段(收藏版)
2019/12/17 Javascript
Vue切换组件实现返回后不重置数据,保留历史设置操作
2020/07/21 Javascript
vue制作toast组件npm包示例代码
2020/10/29 Javascript
三剑客:offset、client和scroll还傻傻分不清?
2020/12/04 Javascript
[01:04]不如跳舞!DOTA2新英雄玛尔斯的欢乐日常
2019/03/11 DOTA
Python+django实现文件上传
2016/01/17 Python
Python实现二分查找与bisect模块详解
2017/01/13 Python
关于Python如何避免循环导入问题详解
2017/09/14 Python
Python实现判断一个整数是否为回文数算法示例
2019/03/02 Python
python3 批量获取对应端口服务的实例
2019/07/25 Python
OpenCV+face++实现实时人脸识别解锁功能
2019/08/28 Python
Django实现whoosh搜索引擎使用jieba分词
2020/04/08 Python
python中元组的用法整理
2020/06/15 Python
python获取百度热榜链接的实例方法
2020/08/25 Python
英国在线泳装店:Simply Swim
2019/05/05 全球购物
金融专业大学生职业生涯规划范文
2014/01/16 职场文书
网络管理员岗位职责
2014/03/17 职场文书
端午节活动总结报告
2015/02/11 职场文书
对讲机知识
2022/04/07 无线电