当前位置: 首页 > 科技观察

使用Content-Visibility优化渲染性能

时间:2023-03-22 14:08:23 科技观察

最近在业务中使用了content-visibility来优化渲染性能。这是一个相对较新且功能强大的属性。本文将带领您深入了解它。什么是内容可见性?content-visibility:属性控制元素是否呈现其内容,这允许用户代理(浏览器)在需要时可能省略大量布局和呈现工作。MDN原文:content-visibilityCSS属性控制元素是否完全呈现其内容,并强制包含一组强大的内容,从而允许用户代理潜在地省略大量的布局和呈现工作,直到它变得非常需要为止。Basic使用户代理能够跳过元素的渲染工作(包括布局和绘画)直到需要它——这使得初始页面加载速度更快。它有几个共同的价值观。/*关键字值*/content-visibility:visible;内容可见性:隐藏;内容可见性:自动;单独说明:content-visibility:visible:默认值,无作用,相当于不加content-visibility,Elements照常渲染。内容可见性:隐藏:类似于显示:无,用户代理将跳过其内容的呈现。(这里要注意内容的渲染是跳过的)content-visibility:auto:如果元素不在屏幕上,与用户无关,则不会渲染其后代元素。contain-intrinsic-size当然,除了content-visibility,还有一个支撑属性--contain-intrinsic-size。contain-intrinsic-size:控制由内容可见性指定的元素的固有大小。上面两个属性光看定义和介绍会有点混乱。我们先来看看content-visibility具体是怎么用的。content-visibility:visible是默认值,加上之后没有任何作用,我们直接跳过。使用content-visibility:hidden来优化显示切换。首先,让我们看一下content-visibility:hidden。它通常与display:none进行比较,但它们之间还是有很大的区别。首先,假设我们有两个DIV环绕框:

1111
2222
设置两个div一个黑色200x200块:.g-wrap>div{width:200px;高度:200px;background:#000;}效果如下:OK,没问题,接下来我们给.hidden:hidden设置content-visibility,看看会发生什么:.hidden{content-visibility:hidden;}效果如下:注意,仔细看效果,这里添加content-visibility:hidden后,消失的只是被添加元素的div的子元素消失不见了,但是父元素本身和它的样式仍然存在于页。如果我们去掉设置了content-visibility:hidden的元素本身的width、height、padding、margin等属性,元素看起来就像设置了display:none一样,消失在页面中。那么,content-visibility:hidden的作用是什么?对于设置了content-visibility:hidden的元素,其子元素将被隐藏,但其渲染状态将被缓存。所以,当content-visibility:hidden被移除时,用户代理不需要从头开始渲染它和它的孩子。因此,如果我们将这个属性应用到一些一开始需要隐藏,然后需要在页面某个时刻渲染的元素,或者一些需要频繁切换显示和隐藏状态的元素,渲染效率会提高。一个非常大的改进。使用content-visibility:auto来实现懒加载或者虚拟列表OK,接下来就是content-visibility的核心用法,使用auto属性值。content-visibility:auto的作用是,如果元素在屏幕外且与用户无关,则不会渲染其后代元素。是不是很像LazyLoad?我们来看这样一个DEMO来理解它的功能:假设我们有这样一个HTML结构,里面有很多文本内容:...
//...包含N个段落...
每个.paragraph的内容如下:因此,整个页面看起来是这样的:因为,我们有没有处理任何页面内容,所以所有的.paragraphs都会在页面刷新的那一刻渲染出来,看到的效果如上图。当然,现代浏览器正变得越来越智能。基于这种场景,我们真的希望我们可以延迟加载尚未看到或滚动到的区域。只有当我们需要显示和滚动到那个地方时,才会渲染之前的页面内容。基于这种场景,content-visibility:auto应运而生,让浏览器判断设置了这个属性的元素,如果当前不在视口中,则不渲染该元素。在上面的代码的基础上,我们只需要最小化,加上这么一段代码:.paragraph{content-visibility:auto;}然后看效果,仔细观察右边的滚动条:这里我用的是::-webkit-scrollbar相关样式使滚动条更明显。可能你还没有意识到发生了什么,我们对比了添加content-visibility:auto和不添加content-visibility:auto两种效果下的文字整体高度,有非常明显的区别,因为设置Elementswithcontent-visibility:auto当前不在不可见区域呈现。所以右边内容的高度其实比正常状态下少了很多。好吧,让我们真正开始滚动,看看会发生什么:由于下面的元素只有在滚动过程中出现在视口内时才会被渲染,所以滚动条有明显的无规律抖动。(当然,这也是使用content-visibility:auto的小问题之一),但是可以很明显的看出,这和我们平时使用JavaScript实现的lazyloading或者lazyloading非常相似。当然,和懒加载不同的是,在向下滚动的过程中,上面消失的已经渲染消失在视口中的元素,也会因为消失在视口中而再次隐藏。因此,即使页面滚动到底部,滚动条的整体高度也保持不变。内容可见性可以优化渲染性能吗?那么,content-visibility可以优化渲染性能吗?在Youtube--Slashinglayoutcostwithcontent-visibility[1]中,给出了一个很好的例子。这里我简单复现一下。对于一个包含大量HTML内容的页面,比如这个页面--HTML-LivingStandard[2],你可以感觉到向下滚动,没有尽头。(这里我是在本地模拟页面,把页面的DOM全部复制过来,并没有在网站上实际测试)如果不对这个页面做任何处理,看看第一次渲染的耗时:可以看到DOMContentLoaded耗时3s+,足足2900ms花在了Rendering上!而如果在这个页面的每一段都加上content-visibility:auto,再看整体耗时:可以看到DOMContentLoaded的时间已经降到了500ms+,Rendering的耗时直接优化为61毫秒!2900ms-->61ms,可谓是惊人的优化程度。因此content-visibility:auto对长文本和长列表功能的优化是显而易见的。使用contain-intrinsic-size解决滚动条抖动的问题当然content-visibility也有一些小问题。从上面的例子我们也可以看出,当使用content-visibility:auto来处理长文本和长列表时。滚动页面的时候,滚动条一直抖动,体验不是很好。当然,这也是很多虚拟榜单都会存在的一些问题。幸运的是,规范制定者也发现了这个问题。这里我们可以使用另一个CSS属性,也就是文章开头提到的另一个属性--contain-intrinsic-size来解决这个问题。contain-intrinsic-size:控制由内容可见性指定的元素的固有大小。这意味着什么?还是上面的例子...//...包含N个段落...如果我们不使用contain-intrinsic-size,只对视口外的元素使用content-visibility:auto,那么视口外元素的高度通常为0。当然,如果你直接为父元素设置一个固定的高度,就会有一个高度。然后是实际的滚动效果,滚动条在晃动:因此,我们可以同时使用contain-intrinsic-size,如果我们能准确知道在渲染状态下设置了content-visibility:auto的元素的高度,填写相应的高位。如果你准确知道高度,你也可以填写一个近似值:.paragraph{content-visibility:auto;contain-intrinsic-size:320px;}之后,浏览器会给未实际渲染的视口.paragraph元素的高度,避免滚动条抖动的现象:大家可以自己试试:CodePenDemo--content-visibility:autoDemo[3]content-visibility的其他一些问题首先看一下content-visibilityCompatibility(2022-06-03):现在很惨淡,我还没有实际在业务中使用它,所以我得等一会儿。当然,由于这个属性属于渐进增强的功能,所以即使失败了,也完全不会影响页面本身的显示。同时也有同学表示使用content-visibility:auto只能解决部分场景,在海量DOM场景下的实际效果还有待进一步测试。实际使用时,多做比较再做选择。当然,现代浏览器越来越智能,类似于content-visibility功能的属性也越来越多。我们在性能优化的道路上有了更多的选择,总是好事。最后,本文到此结束,希望对你有所帮助:)参考[1]Youtube--Slashinglayoutcostwithcontent-visibility:https://www.youtube.com/watch?v=FFA-v-CIxJQ&t=869s。[2]HTML-生活标准:https://html.spec.whatwg.org/。[3]CodePen演示--content-visibility:auto演示:https://codepen.io/Chokcoco/pen/rNJvPEX。