Code前端首页关于Code前端联系我们

什么是内容可见性?优化屏幕切换性能,修复滚动条抖动

terry 2年前 (2023-09-27) 阅读数 62 #数据结构与算法

业务实际使用内容可视性做了一些渲染性能优化。

这是一个相对较新的功能,功能强大。本文将带您深入了解。

什么是内容可见性

内容可见性:属性控制元素是否渲染其内容,允许用户代理(浏览器)在需要时跳过大量布局和渲染工作。

MDN 原文:内容可见性 CSS 属性控制元素是否渲染其内容,同时强制执行一组强大的包含,允许用户代理潜在地省略大量布局和渲染工作,直到它成为基本上,它允许用户代理跳过元素的渲染工作(包括布局和绘制)直到需要它 - 使初始页面加载速度更快。

它有几个共同的值。

/* Keyword values */
content-visibility: visible;
content-visibility: hidden;
content-visibility: auto;

逐一解释一下:

  • content-visibility:可见:默认值,无效果,相当于不添加content-visibility的渲染,元素与正常一样。
  • 内容可见性:隐藏:与显示:无类似,用户代理会跳过其内容的呈现。 (这里需要注意的是,跳过的是内容的渲染)
  • content-visibility: auto:如果元素不在屏幕上且与用户无关,则不会重现其后代元素。

contain-intrinsic-size

除了 content-visibility 当然还有一个匹配属性 -- contentcontent-

contain-intrins ic尺寸 :控制由 content-visibility 指定的元素的自然大小。

上面两个属性的定义和介绍有点混乱。

首先我们来看看如何具体使用content-visibility

内容可见性:可见是默认值。添加后没有效果,我们直接跳过。

使用 content-visibility:hidden 来优化屏幕切换性能

首先看,它通常使用:hidden-visibility screen : none 比较,但是事实上,它们之间还是存在很大差异的。

首先假设我们有两个DIV换行盒子:

<div class="g-wrap">
    <div>1111</div>
    <div class="hidden">2222</div>
</div>

将两个div设置为200x200的黑块: 问题如下: ,接下来,我们设置.hidden。 其中content-visibility:hidden看看会发生什么:

.hidden {
    content-visibility: hidden;
}

效果如下:没有,仔细看:这里添加了

  • content-visibility:hidden在之后 消失,只有添加该元素的 div 的子元素消失,而父元素本身及其样式仍然存在于页面

    ❝ 上。

    如果我们用删除元素本身的宽度高度、 padding

    具有 margin 等属性,元素看起来就像设置了 display: none 并从页面上消失。

    那么,内容可见性:隐藏的作用是什么?

    对于设置了content-visibility:hidden的元素,其子元素将被隐藏,但其渲染状态将被缓存。因此,当删除 content-visibility:hidden 时,用户代理不必重新开始渲染它及其子项。

    因此,如果我们将该属性应用到一些首先需要隐藏,但随后又需要在页面某个时间渲染的元素,或者一些需要频繁切换显示和隐藏状态的元素,渲染效率将会发生非常大的提升。

    使用 content-visibility: auto 实现虚拟列表

    OK,接下来是 content-visibility 的核心使用,使用 ❝ 属性值。

    content-visibility: auto 的作用是,如果元素不在屏幕上并且与用户不相关,则不会渲染其后代元素。是不是和LazyLoad很相似?

    我们看这样一个DEMO来了解它的功能:

    假设我们有这样一个包含大量文本内容的HTML结构:

    <div class="g-wrap">
        <div class="paragraph">...</div>
        // ... 包含了 N 个 paragraph
        <div class="paragraph">...</div>
    </div>

    每个.section的内容。如下:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    所以整个页面是这样的:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    由于我们没有对页面内容进行任何处理,所有.paragraph都会在页面刷新的瞬间渲染出来。你看到的效果如上图所示。

    当然,现代浏览器变得越来越智能。基于这个场景,我们实际上非常希望那些没有看到或滚动到的区域能够被延迟到我们需要显示它并滚动到它的时候。 ,页面内容被复制。

    基于此场景,出现了内容可见性:自动。它允许浏览器对具有此属性集的元素进行评级。如果该元素当前不在视口中,则不会渲染该元素。

    在上面的代码的基础上,我们只需要最小化它,添加这样的代码片段即可:

    .paragraph {
        content-visibility: auto;
    }

    再看一下效果,仔细观察右边的滚动条:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    这里我用了::- webkit-scrollbar相关样式,让滚动条更加明显。

    也许你没有意识到发生了什么。我们来对比一下添加 content-visibility: auto 和不添加 content-visibility: auto 的两种效果 整体高度:❀ 有非常明显的区别。这是因为具有 content-visibility: auto 的元素设置在不可见区域,当前未渲染。因此,内容在右侧。事实上,身高比正常人要低很多。

    好吧,让我们实际开始滚动,看看会发生什么:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    由于下面的元素仅在滚动过程中出现在视口区域内时才会渲染,因此滚动条显得明显不稳定。抖动现象。 (当然,这也是使用 content-visibility: auto 的小问题之一),但是很明显,这与我们通常使用 JavaScript 实现的虚拟列表非常相似。

    在向下滚动的过程中,已经渲染并在视口中消失的元素当然也会再次隐藏,因为它们在视口中消失了。因此,即使页面滚动到底部,整体滚动条高度也不会改变。

    内容可见性渲染性能可以优化吗?

    那么,content-visibility能够优化渲染性能吗?

    在 Youtube – 通过内容可见性削减布局成本,给出了一个很好的例子。

    我只是想在这里重现它。

    对于包含大量 HTML 内容的页面,例如此页面 - HTML - Living Standard

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    ,您可能会注意到,如果向下滚动,您永远不会到达末尾。(这里我在本地模拟了页面,复制了整个页面的DOM,并没有在网站上实际测试)

    如果不对这个页面做任何处理,看一下第一次渲染所花费的时间:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    Ok 看吧,DOMContentLoaded 的时间为 3s+,渲染所花费的时间为 2900ms❀

    如果添加 内容可见性:自动到这个页面的各个部分,然后看一下整体的耗时:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    可以看到 DOMContentLoade 的时间急剧下降到了500ms+,渲染的时间直接优化为61ms

    2900ms --> 61ms,这是一个非常棒的优化水平。因此,内容可视性:auto对于长文本和长列表功能的优化是显而易见的。

    使用 contain-intrinsic-size 修复滚动条抖动问题

    当然❙❝ 或 min❙ 可见性问题。

    从上面的示例中您还可以看到,当您使用 content-visibility: auto 来处理长文本和长列表时。滚动页面时滚动条不断晃动,体验不太好。

    这当然也是很多虚拟列表都存在的问题。

    幸运的是,规格制定者也发现了这个问题。这里我们可以使用另一个CSS属性,也就是文章开头提到的另一个属性——contain-intrinsic-size,来解决这个问题。

    contain-intrinsic-size:控制由content-visibility指定的元素的原始大小。

    这是什么意思? ?元素高度一般为0。

    当然,如果直接给父元素设置一个固定的高度,也会有一个高度。

    所以实际的滚动效果,滚动条抖动:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    所以我们可以同时使用contain-intrinsic-size如果我们能准确的知道设置的话visibility:对于auto的高度渲染模式下的

    元素,填充相应的高度。如果你准确知道高度,也可以填一个近似值:

    .paragraph {
        content-visibility: auto;
        contain-intrinsic-size: 320px;
    }

    此后,浏览器会给视口外的.paragraph元素赋予一个高度,避免实际渲染。滚动。条形抖动现象:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    您可以自己尝试一下:CodePen 演示 -- content-visibility: auto 演示点击查看示例

    content-visibility: auto❀

  • ❀❀ ,VS Lazy内容可见性:自动可以取代LazyLoad吗?

    我们看一下我们平时对LazyLoad的定义。

    LazyLoad:一般来说,LazyLoad的作用就是当页面没有滚动到对应区域时,不会加载该区域的资源(网络请求)。反之,当页面滚动到相应区域时,就会开始请求相关资源。

    所以如果content-visibility: auto要能够替代LazyLoad,就必须在初始化渲染时将content-visibility:设置在页面当前显示区域之外。 auto元素中的一些静态资源将不会被加载。

    这里尝试做一个简单的DEMO:

    还是使用上面的代码,假设我们有如下的HTML结构,即根据上面的代码,插入一些图片资源:

    <div class="g-wrap">
        <div class="paragraph">...</div>
        // ... 包含了 N 个 paragraph
        <div class="paragraph">...</div>
        <div class="g-img">
          <img >
        </div>
        <div class="g-img">
          <img >
        </div>
        <div class="g-img">
          <img >
        </div>
    </div>

    相应设置CSS :

    .paragraph,
    .g-img {
        content-visibility: auto;
    }

    刷新页面时,观察网络请求(网络)的状态:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    即使当前页面可见区域之外的内容没有渲染,图片依然会被加载!

    因此,这也引出了一个很重要的结论:

    Content-Visibility: Auto 不能直接替换 LazyLoad,而设置 Content-Visibility: Auto 的元素是direct 可视区域以外的区域不会渲染,但页面初始化时仍然会加载里面的静态资源

    所以,在实际使用中,如果你的公司已经使用了比较完善的Lazyload来处理长列表或者一些图片资源,那么内容可视性:auto并不是更好的选择。

    探索辅助功能

    当然,内容可见性的功能:自动导致了另一个有趣的点。

    如果可视区域之外的内容不渲染,会影响用户的全文搜索吗?毕竟这是一个非常重要的功能。

    让我们再做一次调查。依然是上面的DEMO。我们在开头和结尾添加两个特殊字符串:

    <div class="g-wrap">
        <div class="text">
            <p>content-visibility: auto 对搜索功能影响的探究</p>
        </div>
        <div class="paragraph">...</div>
        // ... 包含了 N 个 paragraph
        <div class="paragraph">...</div>
        <div class="text">
            <p>content-visibility: auto 对搜索功能影响的探究</p>
        </div>
    </div>

    相应设置CSS:

    .paragraph,
    .text {
        content-visibility: auto;
    }

    好了,这样页面刷新后,第二个.text就处于非渲染状态。我们尝试全局搜索ctrl + F,看看能找到多少个:

    content-visibility是什么?优化展示切换性能,解决滚动条抖动问题

    一个很有趣的现象,全局搜索的时候,可以找到当前没有渲染的元素的内容。

    这里我们还可以得到另一个非常重要的点:

    即使有未渲染的元素设置了content-visibility: auto,也不会影响全局搜索功能。

    这也是内容可视性设计上的充分考虑,可访问性或用户体验的考虑。由此看来,它的实际使用还有一些考虑。很有帮助。

    内容可见性

    首先,查看 内容可见性

  • ' (6-03-0:❓) 的兼容性,网址为目前我还没有在商业中实际使用过它,所以还需要等待一段时间。由于这个属性是渐进增强的特性,所以即使失败,显然也完全不会影响页面本身的显示。

    同时也有同学表示,使用内容可视性:auto只能解决部分场景,海量DOM场景下的实际效果还需要进一步测试。实际使用时,多做比较,做出选择。

    当然,现代浏览器已经变得越来越智能,类似内容可见性的属性也越来越多。我们在性能优化的道路上有了更多的选择,这总是一件好事。 。

    总结

    总结一下:

    1. 在一些经常需要在可见和隐藏状态之间切换的元素上,使用 内容可见性:隐藏 ❀ 代理不需要再次开始播放。及其子元素,可以有效提高切换时的渲染性能;
    2. 内容可见性:自动看起来更像是一个虚拟列表。使用它可以极大地改善长列表和长页面文本的渲染。表现;
    3. 合理利用contain-intrinsic-size估计可以设置内容可见性的高度和宽度:auto元素可以有效避免滚动过程中的滚动。 ;
    4. 内容可见性:auto无法直接替代LazyLoad。设置了 content-visibility: auto 的元素不会在可视区域之外渲染,但它们内部的静态资源仍然存在。初始化时页面全部加载;
    5. 即使存在设置了 content-visibility: auto 的未渲染元素,也不会影响全局搜索功能。

    终于

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    热门