如何只使用 CSS 提升页面渲染速度
提升页面渲染速度的 4 个 CSS 技巧

用户都喜欢能快速加载的网页应用。如果用户浏览的过程中页面出现延迟,用户极有可能立即关闭该页面。本文重点介绍 4 个提升页面渲染速度的 CSS 技巧,帮助开发者提升用户体验。


1. Content-visibility

大多数网页应用的 UI 元素很复杂且扩展能力极强,其扩展超出了用户通过浏览器视图(屏幕)看到的范围。我们可以用 content-visibility 跳过屏幕外内容的渲染,如果屏幕外内容很多,就可以大幅减少页面渲染时间。

这是新增的功能,能有效提高渲染能力。content-visibility 接受数个值,我们可以在一个元素上使用 content-visibility: auto; 来快速提高渲染能力。

下列页面包括多个信息卡,一个屏幕大概能放下 12 个信息卡,列表中共有大约 375 个卡,浏览器渲染整个页面一共需要 1037 毫秒。

常规 HTML 页面

现在,将 content-visibility 添加到所有卡。

content-visibility 添加到页面后,渲染时间减少到 150 毫秒,比之前快 6 倍以上。

由此可见,content-visibility 可以有效地缩短页面渲染时间。

content-visibility 的局限性

content-visibility 也有其局限性,比如:

  • 此功能仍处于试验阶段。截止目前,Firefox(PC 和 Android 版本)、Internet Explorer(IE 浏览器没有添加此功能的计划)和 Safari(Mac 和 iOS)都不支持 content-visibility
  • 滚动条会出现异常。因为元素最初是以 0 像素的高度渲染,所以向下拖动滚动条时,这些元素就会进入屏幕。实际内容被渲染,元素的高度也随之更新,滚动条会表现异常。

添加了 content-visibility 的滚动条

要解决滚动条表现异常的问题,可以使用另一个 CSS 属性—— contain-intrinsic-size。它规定元素的自然大小,元素会以既定的高度而非 0 像素来渲染。

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

我在试验中发现,就算使用了 containt-intrinsic-size,如果我们把大量带有 content-visibility 的元素设置为 auto,滚动条还是会出现一些小问题。

因此,我建议大家计划好布局,分几个部分,在各个部分使用 content-visibility,保证滚动条正常运行。


提示:使用 Bit Github在项目间共享可重用组件。

Bit 能简化在项目之间共享、记录和重复使用独立组件的步骤使用 Bit 可以使代码重复利用率最大化,保持设计的一致性,使团队高效协作,提高交付效率,构建可扩展的应用程序。

Bit 支持 Node、React Native、React、Vue、Angular 等。


示例:React在Bit.dev上共享的组件

2. Will-change 属性

浏览器中的动画通常与其他元素一起渲染,现在,浏览器可以使用 GPU 优化一些动画操作。

如果一个元素有 will-change 属性,我们就能修改具体属性,让浏览器提前执行一些必要的优化。

然后,浏览器为该元素创建一个单独的层,将该元素的渲染连同其他优化项目委托给 GPU。随着 GPU 加速接管动画渲染,动画会更加流畅。

请参考下列 CSS 类:

// In stylesheet
.animating-element {
  will-change: opacity;
}
// In HTML
<div class="animating-elememt">
  Animating Child elements
</div>

在浏览器中渲染以上代码段时,它会识别 will-change 属性,并提前优化与透明度相关的更改。

参考 Maximillian Laumeister 的性能基准,改变一行代码获得了超过 120 帧的渲染速度,之前的速度大约为 50 帧。


不使用 will-change


使用 will-change

什么时候不使用 will-change

如上所述,will-change 可以提高性能,但如果使用不当反而会降低网页应用的性能。

  • 使用 will-change 意味着该元素会发生变化。
    如果你同时使用 will-change 和动画,就不能实现优化。因此,我建议在父元素上使用 will-change,在子元素上使用动画。
.my-class{
  will-change: opacity;
}

.child-class{
  transition: opacity 1s ease-in-out;
}
  • 不要在非动画元素上使用。
    在元素上使用 will-change 时,浏览器会通过将元素移到新的一层并将转换移交给 GPU 来实现优化。如果你没有要转换的内容,就会浪费资源。

注意,建议在所有动画完成后从元素中删除 will-change

3. 缩短渲染阻止时间

许多网页应用都要适用各种形状因数,包括 PC、平板电脑和移动电话等。要实现这些响应,必须根据媒体尺寸编写新样式。页面渲染只有在 CSS 对象模型(CSSOM)准备就绪后才能开始。网页应用程序需要拥有一个较大的样式表才能适应所有设备的形状因数。

然而,如果我们根据形状因数分出多个样式表,只能让主要 CSS 文件阻止关键路径,让其优先下载,之后再下载其他样式表。
<link rel="stylesheet" href="styles.css">


单个样式表

分成多个样式表:

<!-- style.css contains only the minimal styles needed for the page rendering -->
<link rel="stylesheet" href="styles.css" media="all" />
<!-- Following stylesheets have only the styles necessary for the form factor -->
<link rel="stylesheet" href="sm.css" media="(min-width: 20em)" /><link rel="stylesheet" href="md.css" media="(min-width: 64em)" /><link rel="stylesheet" href="lg.css" media="(min-width: 90em)" /><link rel="stylesheet" href="ex.css" media="(min-width: 120em)" /><link rel="stylesheet" href="print.css" media="print" />

如上所述,参照形状因数将样式表分成多个样式表可以缩短渲染阻止时间。

4. 避免使用 @import 包含多个样式表

使用 @import 可以在一个样式表中包含另一个样式表。在大型项目中使用 @import 可以简化代码。

重要的是,@import 是一个阻塞调用,须通过发出网络请求来获取、解析文件,再将其包含到样式表中。在样式表中嵌套 @import 会影响渲染效果。
# style.css
@import url("windows.css");
# windows.css
@import url("componenets.css");


Waterfall with imports

我们可以使用多个链接同时加载样式表,比使用 @import 的效果更好。


总结

以上就是改善网页性能的 4 个 CSS 技巧。content-visibility 是 CSS 的最新功能之一,很有发展前景,因为它可以通过页面渲染从多个方面提升性能。

重点是,我们不需要编写任何 JavaScript 代码即可提升这些性能。

我相信以上技巧可以帮助大家为终端用户构建性能更好的网页应用,希望本文对大家有所帮助!

如有任何问题或建议,欢迎在下方评论,感谢大家的阅读!



原文作者:Rumesh Eranga Hapuarachchi
原文链接:https://blog.bitsrc.io/improve-page-rendering-speed-using-only-css-a61667a16b2


推荐阅读
相关专栏
前端与跨平台
90 文章
本专栏仅用于分享音视频相关的技术文章,与其他开发者和声网 研发团队交流、分享行业前沿技术、资讯。发帖前,请参考「社区发帖指南」,方便您更好的展示所发表的文章和内容。