vlambda博客
学习文章列表

2020年CSS新特性-Web性能


contain 和 content-visibility


这两个属性是属于 CSS容器模块 的,其最大的特点应该是可以帮助Web开发者提高Web页面的性能:

当容器的内容发生变化时,浏览器考虑到其他元素可能也会发生变化,于是就会去检查页面中所有的元素。一直以来浏览器都是这么做的,大家都习以为常了。但从另一方面来说,开发者很清楚当前修改的元素是否独立、是否影响其他元素。因此如果开发者能把这个信息通过CSS告诉浏览器,那么浏览器就不需要再去考虑其他元素了,这就是非常完美的事情。而CSS容器模块中的contain属性就为我们提供了这种能力。

们来看@Manuel Rego Casasnovas在《An introduction to CSS Containment(https://blogs.igalia.com/mrego/2019/01/11/an-introduction-to-css-containment/?ref=heydesigner)》文章中提供的一个示例(https://blogs.igalia.com/mrego/files/2019/01/css-contain-example.html)

假设一个页面有很多个元素,在这个示例中,我们有10000个这样的元素:

<div class="item"> <div>Lorem ipsum...</div></div>

使用JavaScript的textContent这个API来动态更改div.item > div的内容:

const NUM_ITEMS = 10000; const NUM_REPETITIONS = 10; function log(text) {  let log = document.getElementById("log");  log.textContent += text; } 
function changeTargetContent() { log("Change \"targetInner\" content...");
// Force layout. document.body.offsetLeft; let start = window.performance.now(); let targetInner = document.getElementById("targetInner"); targetInner.textContent = targetInner.textContent == "Hello World!" ? "BYE" : "Hello World!";
// Force layout. document.body.offsetLeft; let end = window.performance.now(); let time = window.performance.now() - start; log(" Time (ms): " + time + "\n");
return time; }
function setup() { for (let i = 0; i < NUM_ITEMS; i++) { let item = document.createElement("div"); item.classList.add("item"); let inner = document.createElement("div"); inner.style.backgroundColor = "#" + Math.random().toString(16).slice(-6); inner.textContent = "Lorem ipsum..."; item.appendChild(inner); wrapper.appendChild(item); } }

如果不使用contain,即使更改是在单个元素上,浏览器在布局上的渲染也会花费大量的时间,因为它会遍历整个DOM树(在本例中,DOM树很大,因为它有10000个DOM元素):

2020年CSS新特性-Web性能

在本例中,div的大小是固定的,我们在内部div中更改的内容不会溢出它。因此,我们可以将contain: strict应用到项目上,这样当项目内部发生变化时,浏览器就不需要访问其他节点,它可以停止检查该元素上的内容,并避免到外部去。

2020年CSS新特性-Web性能

CSS容器模块中的content-visibility属性会显著影响第一次下载和第一次渲染的速度。此外,你可以立即与新渲染的内容交互,而无需等待内容的其余部分加载。该属性强制用户代理跳过不在屏幕上的标记和绘制元素。实际上,它的工作方式类似于延迟加载,只是不加载资源,而是渲染资源。

简单地说,CSS的content-visibility属性 可跳过不在屏幕上的内容渲染,包括布局(Layout)和渲染(Paint),直到真正需要布局渲染的时候为止。所以利用它可以使用初始用户加载速度更快,还能与屏幕上的内容进行更快的交互。

2020年CSS新特性-Web性能

上图来自于@Una Kravets和@Vladimir Levin的《content-visibility: the new CSS property that boosts your rendering performance(https://web.dev/content-visibility/)》一文。从图中我们可以获知,使用content-visibility: auto属性可使分块的内容区域的初始加载性能提高7倍。

有关于这方面的介绍,还可以阅读:

  • CSS Containment in Chrome 52(https://developers.google.com/web/updates/2016/06/css-containment)

  • Helping Browsers Optimize With The CSS Contain Property(https://www.smashingmagazine.com/2019/12/browsers-containment-css-contain-property/)

  • An introduction to CSS Containment(https://blogs.igalia.com/mrego/2019/01/11/an-introduction-to-css-containment)

  • Let’s Take a Deep Dive Into the CSS Contain Property(https://css-tricks.com/lets-take-a-deep-dive-into-the-css-contain-property/)

  • CSS Containment(https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Containment)

  • content-visibility: the new CSS property that boosts your rendering performance(https://web.dev/content-visibility/)

  • Short note on content-visibility: hidden(https://html5accessibility.com/stuff/2020/08/25/short-note-on-content-visibility-hidden/)

  • Using content-visibility: hidden(https://www.w3.org/TR/css-contain-2/#using-cv-hidden)

  • Using content-visibility: auto(https://www.w3.org/TR/css-contain-2/#using-cv-auto)

数据服务


数据服务指的是 Data Saver。啥意思呢?不做解释,直接用一段代码来描述:

@media (prefers-reduced-data: reduce) { header { background-image: url(/grunge.avif); }}

我想大家对于@media (prefers-reduced-data: reduce)应该不会陌生吧。是的,它就是我们所说的CSS媒体查询。只不过稍有不同的是,这个媒体查询是根据用户在设备上的设置喜好来做条件判断。比如上面示例代码,当用户在设备上开启了“Low Data Mode”(低数据模式),会加载grunge.avif图像,可以帮助iPhone上的应用程序减少网络数据的使用:

2020年CSS新特性-Web性能

到目前为止,CSS媒体查询提供了多个媒体特性,可以以用户在设备上的喜好设置做为判断,比如iOS13+开始,iPhone提供的DarkMode模式(prefers-color-scheme(https://www.atatech.org/articles/153525)

2020年CSS新特性-Web性能

比如,使用prefers-reduced-motion媒体查询用于检测用户的系统是否被开启了动画减弱功能:

2020年CSS新特性-Web性能

上面提到的这些媒体查询条件都是在 CSS Media Queries Level 5(https://www.w3.org/TR/mediaqueries-5/) 模块中新增的。

除了上面提到的之外,还有一些我们平时很少见的媒体查询条件,比如:

@media (hover: hoveer) {}
@media (hover: none) and (pointer: coarse) {}
@media (hover: none) and (pointer: fine) {}
@media print and (min-resolution: 300dpi) {}
@media (scan: interlace) {}
@media (update) {}
@media(environment-blending: additive){}
@media (color) {}

变量字体


变量字体是一个非常有意思的CSS特性,它也常被称为“可变字体”,先给大家展示一个Demo(https://codepen.io/airen/pen/yLNpQQW)

2020年CSS新特性-Web性能

变量字体的目标是让网站性能更好,同时给用户提供了更多选择和扩展。变量字体是类似矢量图形,允许为各种字体轴定义不同的值。变量字体设计中一般有五个注册轴,包括字体、字宽、斜体和光学尺寸。每个注册轴都有一个对应的四个字母的标记,可以映射到现有的CSS属性:

2020年CSS新特性-Web性能

除了注册轴之外,字体设计器还可以包含自定义轴。自定义轴让可变字体变得更具创造性,因为不限制自定义轴的范围、定义或数量。与注册轴类似,自定义轴具有相应的四个字母标记。但是,自定义轴的字母标记必须是大写的。例如,你定义了一个注册轴是grade,其对应的字母标记是 GRAD

比如上面示例效果对应的代码:

.text { font-weight: 800; font-style: italic; font-variation-settings: "SSTR" 183, "INLN" 648, "TSHR" 460, "TRSB" 312, "TWRM" 638, "SINL" 557, "TOIL" 333, "TINL" 526, "WORM" 523; transition: font-variation-settings .28s ease;} 
.text:hover { font-weight: 400; font-style: normal; font-variation-settings: "SSTR" 283, "INLN" 248, "TSHR" 160, "TRSB" 112, "TWRM" 338, "SINL" 257, "TOIL" 133, "TINL" 426, "WORM" 223;}

在Firefox浏览器中,我们还可以通过开发者工具中“字体”选项提供的相关可变字体注册轴的值调整:

2020年CSS新特性-Web性能

调整完之后,可以获得新代码:

p { font-size: 60px; line-height: 37px; letter-spacing: 0.113em; font-variation-settings: "SSTR" 450, "INLN" 741, "TSHR" 292, "TRSB" 497, "TWRM" 173, "SINL" 557, "TOIL" 728, "TINL" 526, "WORM" 523, "TFLR" 362, "TRND" 516, "SWRM" 536, "TSLB" 509; font-weight: 491;}

对应效果如下: