关于前端:两行CSS让页面提升了近7倍渲染性能

5次阅读

共计 4100 个字符,预计需要花费 11 分钟才能阅读完成。

前言

对于前端人员来讲,最令人头疼的应该就是页面性能了,当用户在拜访一个页面时,总是心愿它可能疾速出现在眼前并且是可交互状态。如果页面加载过慢,你的用户很可能会因而离你而去。所以页面性能对于前端开发者来说堪称是重中之重,其实你如果理解页面从加载到渲染实现的整个过程,就晓得应该从哪方面下手了。

嗯,不要跑偏了,明天咱们次要来钻研长列表页面的渲染性能

现如今的页面越来越简单,一个页面往往承载着大量的元素,最常见的就是一些电商页面,数以万计的商品列表是怎么保障渲染不卡顿的,大家在面对这种长列表渲染的场景下,个别都会采纳分页或者虚构列表来减缓页面一次性渲染的压力,但这些形式都须要配合 JS 来时实现,那么有没有仅应用 CSS 就可能实现的计划呢?

答案是有的,它就是咱们明天的配角 —— 内容可见性(content-visibility)

如果这篇文章有帮忙到你,❤️关注 + 点赞❤️激励一下作者,文章公众号首发,关注 前端南玖 第一工夫获取最新文章~

content-visibility

属性值

content-visibility是 CSS 新增的属性,次要用来进步页面渲染性能,它能够管制一个元素是否渲染其内容,并且容许浏览器跳过这些元素的布局与渲染。

  • visible:默认值,没有任何成果,相当于没有增加content-visibility,渲染成果与平常统一
  • hidden:与 display: none 相似,浏览器将跳过内容渲染(跳过的是子元素的渲染,不蕴含本身)
  • auto:如果该元素不在屏幕上,并且与用户无关,则不会渲染其子元素

content-visibility: hidden

下面说到 content-visibility: hidden 的成果与 display: none 相似,但其实两者还是有比拟大的区别的:

  • content-visibility: hidden 只是暗藏了子元素,本身不会被暗藏
  • content-visibility: hidden 暗藏内容的渲染状态会被缓存,所以当它被移除或者设为可见时,浏览器不会从新渲染,而是会利用缓存,所以对于须要频繁切换显示暗藏的元素,这个属性可能极大地提高渲染性能。

从着下面咱们能够看到,增加了 content-visibility: hidden 元素的子元素的确是没有渲染,但它本身是会渲染的!

content-visibility: auto 虚构列表

咱们认真想想,页面上尽管会有很多元素,然而它们会同时出现在用户眼前吗,很显然是不会的,用户每次可能实在看到就只有设施可见区那些内容,对于非可见区的内容只有页面不产生滚动,用户就永远看不到。尽管用户看不到,但浏览器却会实实在在的去渲染,以至于节约大量的性能。所以咱们得想方法让浏览器不渲染非可视区的内容就可能达到进步页面渲染性能的成果。

咱们下面说到的虚构列表原理其实就跟这个相似,在首屏加载时,只加载 可视区 的内容,当页面产生滚动时,动静通过计算取得 可视区 的内容,并将 非可视区 的内容进行删除,这样就可能大大提高长列表的渲染性能。

但这个须要配合 JS 能力实现,当初咱们能够应用 CSS 中content-visibility: auto,它能够用来跳过屏幕外的内容渲染,对于这种有大量离屏内容的长列表,能够大大减少页面渲染工夫。

咱们将下面的例子略微改改:

<template>
  <div class="card_item">
    <div class="card_inner">
      <img :src="book.bookCover" class="book_cover" />
      <div class="card_item_right">
        <div class="book_title">{{`${book.bookName}${index + 1}` }}</div>
        <div class="book_author">{{book.catlog}}</div>
        <div class="book_tags">
          <div class="book_tag" v-for="(item, index) in book.tags" :key="index">
            {{item}}
          </div>
        </div>
        <div class="book_desc">
          {{book.desc}}
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {toRefs} from "vue";

const props = defineProps<{
  book: any;
  index: any;
}>();
const {book, index} = toRefs(props);
</script>

<style lang="less" scoped>
.card_item {
  margin: 20px auto;
  content-visibility: auto;
}
  / *
  ...
  */
</style>

首先是没有增加 content-visibility: auto 的成果,无论这些元素是否在可视区,都会被渲染

如果咱们在平时业务中这样写,用户进入到这个页面可能就间接口吐芳香了,为了性能思考,咱们为每一个列表项加上:

.card_item {content-visibility: auto;}

这个时候咱们再来看下成果:

从第 10 个开始,这些没在可视区的元素就没有被渲染,这可比下面那种全副元素都渲染好太多了,然而如果浏览器不渲染页面内的一些元素,滚动将是一场噩梦,因为无奈正确计算页面高度。这是因为,content-visibility会将调配给它的元素的高度(height)视为0,浏览器在渲染之前会将这个元素的高度变为0,从而使咱们的页面高度和滚动变得凌乱。

这里咱们能够看到页面上的滚动条会呈现抖动景象,这是因为可视区外的元素只有呈现在了可视区才会被渲染,这就回导致前后页面高度会发生变化,从而呈现滚动条的诡异抖动景象,这是虚构列表根本都会存在的问题。

contain-intrinsic-size 救场

页面在滚动过程中滚动条始终抖动,这是一个不能承受的体验问题,这个时候咱们能够应用 contain-intrinsic-size 来确保元素的正确渲染,同时也保留提早渲染的益处。

contain-intrinsic-size是与 content-visibility 配套应用的属性,它能够用来管制由 content-visibility 指定的元素天然大小

语法

此属性是以下 CSS 属性的简写:

  • contain-intrinsic-width
  • contain-intrinsic-height
/* Keyword values */
contain-intrinsic-width: none;

/* <length> values */
contain-intrinsic-size: 1000px;
contain-intrinsic-size: 10rem;

/* width | height */
contain-intrinsic-size: 1000px 1.5em;

/* auto <length> */
contain-intrinsic-size: auto 300px;

/* auto width | auto height */
contain-intrinsic-size: auto 300px auto 4rem;

contain-intrinsic-size 能够为元素指定以下一个或两个值。如果指定了两个值,则第一个值实用于宽度,第二个值实用于高度。如果指定单个值,则它实用于宽度和高度。

实现

咱们只须要给增加了 content-visibility: auto 的元素增加上 contain-intrinsic-size 就可能解决滚动条抖动的问题,当然,这个高度约靠近实在渲染的高度,成果会越好,如果切实无奈晓得精确的高度,咱们也能够给一个大略的值,也会使滚动条的问题绝对缩小。

.card_item {
  content-visibility: auto;
  contain-intrinsic-size: 200px;
}

之前没增加 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 并且在非可视区的元素是否存在于可拜访树中?

从这个搜寻中咱们能够看出,content-visibility: auto非可视区内的内容在文档对象模型中依然可用,并且在可拜访性树中(与visibility: hidden 不同)。

是否用来做图片懒加载?

咱们以下面的例子插入一些不同的图片来看看非可视区的图片资源到底会不会加载?

从 Network 中来看,即使这些可视区外的内容没有被渲染,但它们的一些动态资源依然会被加载。这样看来 content-visibility: auto 并不适宜用来做图片懒加载。

兼容性

content-visibility 是 chrome85 新增的个性,所以兼容性还不是很高,

目前来看,content-visibility还不适宜用于理论业务中,但它是一个十分实用的 CSS 属性,置信兼容性的问题在不久的未来会失去解决~

喜爱的同学欢送点个赞呀~ 欢送大家关注公众号 「前端南玖」,如果你想进前端交换群一起学习,请点这里

我是南玖,咱们下期见!!!

正文完
 0