html让两行紧挨着(记录–两行CSS让页面提升了近7倍渲染性能!)
这里给大家分享我在网上总结出来的一些知识 ,希望对大家有所帮助
首先是没有添加content-visibility: auto的效果 ,无论这些元素是否在可视区 ,都会被渲染
如果我们在平常业务中这样写 ,用户进入到这个页面可能就直接口吐芬芳了 ,为了性能考虑 ,我们为每一个列表项加上:
这个时候我们再来看下效果:
从第10个开始 ,这些没在可视区的元素就没有被渲染 ,这可比上面那种全部元素都渲染好太多了 ,但是如果浏览器不渲染页面内的一些元素 ,滚动将是一场噩梦 ,因为无法正确计算页面高度 。这是因为 ,content-visibility会将分配给它的元素的高度(height)视为0,浏览器在渲染之前会将这个元素的高度变为0 ,从而使我们的页面高度和滚动变得混乱 。
这里我们可以看到页面上的滚动条会出现抖动现象 ,这是因为可视区外的元素只有出现在了可视区才会被渲染,这就回导致前后页面高度会发生变化 ,从而出现滚动条的诡异抖动现象 ,这是虚拟列表基本都会存在的问题 。
⚠️注意:当元素接近视口时 ,浏览器不再添加size容器并开始绘制和命中测试元素的内容 。这使得渲染工作能够及时完成以供用户查看 。
这也是为什么上面我们看到的是从第十个才开始不渲染子元素 ,因为它需要一个缓冲区以便浏览器能够在页面发生滚动时及时渲染呈现在用户眼前 。
上面提到的size其实是一种 CSS 属性的潜在值contain ,它指的是元素上的大小限制确保元素的框可以在不需要检查其后代的情况下进行布局 。这意味着如果我们只需要元素的大小 ,我们可以跳过后代的布局 。
contain-intrinsic-size 救场
页面在滚动过程中滚动条一直抖动 ,这是一个不能接受的体验问题 ,为了更好地实现content-visibility ,浏览器需要应用 size containment 以确保内容的渲染结果不会以任何方式影响元素的大小 。这意味着该元素将像空的一样布局 。如果元素没有在常规块布局中指定的高度 ,那么它将是 0 高度 。
这个时候我们可以使用contain-intrinsic-size来指定的元素自然大小 ,确保我们未渲染子元素的 div 仍然占据空间 ,同时也保留延迟渲染的好处 。
语法
此属性是以下 CSS 属性的简写:
contain-intrinsic-width contain-intrinsic-heightcontain-intrinsic-size 可以为元素指定以下一个或两个值。如果指定了两个值,则第一个值适用于宽度 ,第二个值适用于高度 。如果指定单个值 ,则它适用于宽度和高度 。
实现
我们只需要给添加了content-visibility: auto的元素添加上contain-intrinsic-size就能够解决滚动条抖动的问题,当然 ,这个高度约接近真实渲染的高度 ,效果会越好 ,如果实在无法知道准确的高度 ,我们也可以给一个大概的值 ,也会使滚动条的问题相对减少。
之前没添加contain-intrinsic-size属性时 ,可视区外的元素高度都是0 ,现在这些元素高度都是我们设置的contain-intrinsic-size的值 ,这样的话整个页面的高度就是不会发生变化(或者说变化很小) ,从而页面滚动条也不会出现抖动问题(或者说抖动减少)
性能对比
上面说了这么多 ,content-visibility是否真的能够提高页面的渲染性能呢 ,我们来实际对比看看:
首先是没有content-visibility的页面渲染 然后是有content-visibility的页面渲染上面是用1000个列表元素进行测试的 ,有content-visibility的页面渲染花费时间大概是37ms,而没有content-visibility的页面渲染花费时间大概是269ms ,提升了足足有7倍之多!!!
对于列表元素更多的页面 ,content-visibility带来的渲染性能提升会更加明显 。
思考?
能否减小页面的内存占用?
之前有同学问到了content-visibility: auto是否会减少页面内存的占用,这个我们可以查看下使用前后页面所占用内存的大小是否有变化 。
我们可以通过chrome浏览器 设置 --> 更多工具 --> 任务管理器 查看页面占用内存大小 。
首先是没有content-visibility: auto ,页面占用内存大概为96.2MB 然后是添加了content-visibility: auto ,页面占用内存仍然是96.2MB也就是说 ,它并不会减少页面占用内存大小 ,这些元素是真实存在于DOM树中的 ,并且我们也可以通过JS访问到
是否会影响脚本的加载行为?
如果我们在添加了content-visibility: auto的元素内去加载脚本 ,并且此时的元素处于一个不可见的状态 ,那么此时元素内的脚本能够正常加载呢?
很明显它并不会影响脚本与图片的加载行为 ,并且脚本再加载后能够正常执行 。结合上面第一点 ,我们可以得出结论 ,使用了content-visibility: auto的元素影响的只是子元素的渲染 ,对于内部静态资源的加载还是正常进行 。
但我们需要注意的是脚本的执行时机 ,如果要获取DOM元素的话,此时的脚本只能获取到它加载位置之前的DOM元素 ,而与它自身DOM有没有渲染无关!
// 2.js console.log(测试脚本) console.log(第十一个, document.querySelectorAll(.visibility_item)[10]) console.log(第十三个, document.querySelectorAll(.visibility_item)[12]) 复制代码可访问性
使用了content-visibility: auto并且在非可视区的元素是否存在于可访问树中?
这里我们可以看出content-visibility: auto是屏幕外的内容在文档对象模型中仍然可用 ,因此在可访问性树中(与visibility: hidden不同) 。这意味着我们可以在页面上搜索并导航到该内容,而无需等待它加载或牺牲渲染性能 。
这个功能特性是在chrome 90 中更新的 ,在 chrome 85-89 中 ,屏幕外的子元素content-visibility: auto被标记为不可见 。
兼容性
content-visibility是chrome85新增的特性 ,所以兼容性还不是很高 ,但它是一个非常实用的CSS属性 ,由于跳过了渲染 ,如果我们大部分内容都在屏幕外 ,利用该content-visibility属性可以使初始用户加载速度更快 。相信兼容性的问题在不久的将来会得到解决~
本文转载于:
https://juejin.cn/post/7168629736838463525
如果对您有所帮助 ,欢迎您点个关注 ,我会定时更新技术文档 ,大家一起讨论学习 ,一起进步 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!