浏览器之性能指标-CLS(二)

简介: 浏览器之性能指标-CLS(二)

距离分数(Distance fraction)

首先,我们需要计算移动距离

移动距离定义了布局偏移前后给定元素的位置之间的距离。它基本上回答了一个问题:元素移动了多远

一旦计算出移动距离,就可以通过将最大移动距离除以视口的高度来计算距离分数:

最大移动距离 / 视口高度 = 距离分数


计算单个帧的布局偏移

接下来是计算布局偏移分数。我们需要将影响分数乘以距离分数,以获得单个动画帧的布局偏移分数:

影响分数 × 距离分数 = 单个动画帧的布局偏移分数


计算CLS

谷歌在会话窗口中对布局偏移进行分组的处理。

会话窗口实际上是我们的页面生命周期内的时间段,在其中对布局偏移进行汇总。

当页面发生布局偏移时,会打开一个会话窗口。该窗口最长可以持续5秒,但如果在初始偏移后的1秒内没有连续的布局偏移发生,窗口会提前关闭

布局偏移然后在会话窗口内进行汇总。给定页面的最终CLS分数是具有最大总分数的会话窗口的分数 - 其他会话窗口不会影响我们的CLS。

举个例子:

  • 页面开始渲染。
  • 1秒后,发生了一个0.1的布局偏移。
  • 0.5秒后,另一个0.2的偏移发生。
  • 两秒后,发生了一个0.25的偏移,然后页面关闭。
  • 前两个布局偏移发生在同一个会话窗口内,因此我们将它们的分数相加。

第三个布局偏移发生在2秒后(此时,第三个布局偏移和前两个被分在两个不同的会话窗口中),因此它属于一个单独的会话窗口。前一个会话窗口在第二个布局偏移后的1秒后关闭。

因此,在这种情况下,页面的最终CLS分数将为0.1 + 0.2 = 0.30.3>0.25)!第三个布局偏移不影响最终分数。

CLS会忽略在用户输入后的0.5秒内出现的所有布局偏移。这被称为输入排除窗口(input exclusion window)。这意味着在用户与网站进行交互后的500毫秒内,CLS测量会停止。


4. 如何测量 CLS

由于CLS可以在实验室环境真实用户交互中进行测量,我们可以得到CLS实验室分数CLS实际用户数据的两种数据。

使用实验室数据测量CLS

实验室数据意味着使用工具来模拟用户的体验。

这就像实验室测试一样,几乎是真实的,但在受控环境中进行,结果只涵盖了一小部分可能的情况。

我们可以通过以下性能工具访问我们的CLS实验室数据:


使用真实用户数据测量CLS

真实用户数据是基于真实用户交互的数据。由谷歌和其他第三方收集,它可以让我们看到更全面的情况。我们可以将真实用户数据与实验室结果进行比较。对于谷歌来说,真实用户数据的主要来源是Chrome User Experience Report,也称为CrUX

通过以下方式可以访问CrUX数据:


我们从上面挑选一个功能完备并且操作简单的工具 - PageSpeed Insights

它与Google的核心 Web 指标直接相关,因此我们可以直接看到我们的CLS得分如何影响Google对我们的网站的评估。

该服务允许我们输入一个URL,并根据Google过去28天收集的数据为其提供综合性能评分。该评分考虑了多个指标,包括CLS、FCP和LCP。

image.png

在这个测试中,我们选择了一个没有明显CLS的网站。PageSpeed Insights证实了我们的猜想,它返回了极其积极的结果,并显示出较高的CLS得分。

请注意,PageSpeed Insights为每个得分提供了百分比的细分。在这种情况下,91%的用户在加载测试网站时没有经历过布局位移。然而,剩下的访问者确实经历了某种程度的布局位移。

这在CLS和其他核心 Web 指标方面是可以预料的。用户体验会根据他们使用的设备、网络连接和许多其他因素而大大不同。几乎没有办法确保用户永远不会遇到CLS,但我们可以采取预防措施来优化它,使该百分比尽可能低。

除了现场数据外,PageSpeed Insights还提供了所谓的实验室数据

实验室数据是基于单次测试的性能评分,而不是基于长时间收集的数据(被视为现场数据)。

image.png


在我们的测试中,我们获得了一个CLS得分为零,这意味着没有布局位移。针对这一特定测试而言是如此。现在让我们将其与另一个得分没有那么高的网站进行比较。

image.png

为了符合Google的标准,我们的CLS得分应该低于0.10。超过这个值意味着布局发生了显著且明显的位移,这会导致用户体验较差。


什么造成了布局偏移

如果我们想确定网站上哪些元素导致了布局位移,可以使用Chrome开发者工具进行调查。如果我们打开开发者工具(CTRL-SHIFT-I)并切换到"Performance"选项卡,我们可以在浏览网页时记录性能测试。

image.png

在停止录制后,Chrome开发者工具会返回一个时间轴,显示加载时间、各个请求和核心网络指标。从这个时间轴中,我们可以选择Layout Shifts下列出的各个布局位移事件。通过这种方式,我们可以看到它们对应的元素是什么。

image.png

一旦我们知道哪些元素导致了布局位移,我们可以采取措施来解决这个问题。


4. 如何优化 CLS 得分

避免布局偏移

与其事后捶胸顿足,不如防范于未然

排除主要图片的懒加载

通过懒加载,我们可以优化页面的加载并减少启动时的负担。然而,主要图片可能不适合懒加载,特别是如果它在视窗顶部明显显示,因为这种技术可能不是这些元素的最佳解决方案。

使用CSS进行动画

动画可能导致布局偏移,但并非所有动画都会计入CLS分数。chrome忽略CSS变换(transform)的变化 - 因此,如果我们的动画使用CSS的变换属性,它不会影响我们的CLS。

使用CDN

内容分发网络(CDN)是一组地理分布的服务器,可以缓存内容并协同工作以减少响应用户请求所需的时间。服务器响应时间过慢可能导致布局偏移,因此对某些资源使用CDN可能有助于防止页面上的高CLS。

硬编码菜单和页眉

硬编码页眉和菜单元素可以导致页面布局更一致和稳定,因为页眉和菜单的位置和外观始终保持相同。


使用font:display值和link rel=preload

如果我们的网站使用外部托管的字体,它们可能是FOIT(闪烁的不可见文本)和FOUT(闪烁的未样式化文本)的主要原因。

为了避免这种情况,我们可以使用font-display值,例如autoswapblockfallbackoptional

  1. 使用font-display: swap;:这将在字体加载完成之前显示备用字体,然后在字体加载完成后再切换为所需的字体。
@font-face {
  font-family: 'MyWebFont';
  src: url('webfont.woff2') format('woff2'),
       url('webfont.woff') format('woff');
  font-display: swap;
}
  1. 使用font-display: fallback;:这将在字体加载完成之前显示备用字体,然后在字体加载完成后应用所需的字体样式,但可能会导致文本布局变化。
@font-face {
  font-family: 'MyWebFont';
  src: url('webfont.woff2') format('woff2'),
       url('webfont.woff') format('woff');
  font-display: fallback;
}
  1. 使用font-display: optional;:这允许浏览器自行决定是否加载和显示字体,可以提高页面加载性能,但可能会导致字体样式稍后应用。
@font-face {
  font-family: 'MyWebFont';
  src: url('webfont.woff2') format('woff2'),
       url('webfont.woff') format('woff');
  font-display: optional;
}

为了获得更好的效果,我们还可以使用<link rel=preload>预加载字体文件 - 这样,它们将作为优先下载的资源。


为视频和图像包括width和height属性

就网站性能而言,最好使用已经具有精确尺寸的图像。这样,浏览器就不需要在适当地调整大小上花费时间。然而,当无法提供精确尺寸的图像时,我们应为显示的每个图像设置宽度和高度属性。这样,用户的浏览器将准确知道图像的位置,而不需要在最后一刻调整布局。

在互联网的早期,网页开发人员通常在网站的各个地方都包括widthheight属性。它看起来像这样:

<img src="example.jpg" width="800" height="300" alt="示例图像">

随着响应式网页设计的兴起,这种做法变得不那么流行。由于这种新的方法,开发人员开始使用CSS来调整图像的大小。

使用这种方法,只有在浏览器开始下载图像后才会分配空间。在所有图像都显示后,布局会发生变化,导致不必要的偏移。

调整图像大小的更好方法是使用宽高比(aspect ratio)。它是宽度与高度的比例(例如16:9)。

使用宽高比可以让浏览器计算显示图像所需的空间 - 从而减少布局偏移的风险。

srcset属性

如果我们要处理响应式图像,可以使用srcset属性。它允许我们设置多个图片尺寸,并让浏览器显示最合适的尺寸。

当处理响应式图像时,可以使用srcset属性来指定不同大小和分辨率的图像源,让浏览器根据需要选择最合适的图像进行加载和显示。以下是srcset属性的用法示例代码:

<img src="image.jpg" alt="Responsive Image" 
  srcset="image-small.jpg 480w,
          image-medium.jpg 800w,
          image-large.jpg 1200w"
  sizes="(max-width: 600px) 480px,
         (max-width: 900px) 800px,
         1200px"
/>

在上面的示例中,srcset属性指定了三个不同大小和分辨率的图像源,分别是image-small.jpgimage-medium.jpgimage-large.jpg。每个图像源后面的数字(如480w800w1200w)表示图像的宽度。

sizes属性指定了在不同视口宽度下应该使用的图像大小。通过使用媒体查询,可以在不同的视口尺寸下为图像指定不同的大小。

当浏览器根据设备的屏幕大小和分辨率选择加载图像时,它会根据srcset属性和sizes属性的规则选择最合适的图像源,并自动调整图像的大小。

这样,使用srcset属性可以为不同设备和视口尺寸提供最佳的图像质量和性能,实现响应式的图像展示。


使用min-height和min-width CSS属性

我们可以使用min-heightmin-width CSS属性分别设置元素的最小高度和最小宽度。它们可以防止元素变得比指定的大小更小,无论它包含多少内容。

可以使用任何长度单位(如像素)或百分比来指定大小,例如:

div {
  min-height: 300px;
  min-width: 400px;
}

这种解决方案适用于不需要响应式大小而是固定高度或宽度的元素。


为广告预留空间

我们的网站是否显示第三方广告?网站上最常见的做法是在加载期间或加载后动态添加广告内容。在页面的其余部分继续加载时,非广告内容可能会对用户可见。

如果没有为即将到来的广告预留足够的空间,它们可能会在到达时移动可见的非广告内容,这会导致较高的CLS。以下是我们可以解决此问题的方法:

  • 使用CSS的<div>标签为静态广告预留适当的空间。
  • 如果广告槽接受多个尺寸,请为最大或最小尺寸预留空间。
  • 某些类型的广告无法免受布局偏移的影响。流体广告槽会根据接收到的内容自动调整其大小,为广告创作者提供更大的创作自由度。如果必须使用流体广告槽,请确保它们尽快加载,并将它们放置在视窗下方。

利用动画处理页面变化

有效的动画和过渡可以通过平滑地更新页面上的内容而不引起任何惊喜来提升用户体验。

内容突然和不可预测地移动几乎总会导致糟糕的用户体验,但是从一个位置逐渐自然地移动到另一个位置的内容可以帮助用户理解变化。


总的来说,在高CLS得分方面有两个主要的元凶:媒体文件和广告。


后记

分享是一种态度

参考资料:

  1. CLS优化
  2. CLS
  3. 核心 Web 指标
  4. CSS百分比padding实现比例固定图片自适应布局

全文完,既然看到这里了,如果觉得不错,随手点个赞和“在看”吧。

相关实践学习
Serverless极速搭建Hexo博客
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
相关文章
|
Web App开发 存储 JavaScript
浏览器之性能指标-TTI
浏览器之性能指标-TTI
215 0
|
Web App开发 存储 JavaScript
浏览器之性能指标-INP
浏览器之性能指标-INP
135 0
|
Web App开发 前端开发 JavaScript
浏览器之性能指标-TBT
浏览器之性能指标-TBT
220 0
|
前端开发 JavaScript API
浏览器之性能指标-FID(二)
浏览器之性能指标-FID(二)
|
前端开发 JavaScript 搜索推荐
浏览器之性能指标-FID(一)
浏览器之性能指标-FID(一)
258 0
|
前端开发 JavaScript UED
浏览器之性能指标-CLS(一)
浏览器之性能指标-CLS
232 0
|
存储 缓存 前端开发
浏览器之性能指标-LCP
浏览器之性能指标-LCP
121 0
|
Web App开发 缓存 前端开发
浏览器之性能指标_FCP(二)
浏览器之性能指标_FCP(二)
213 0
|
Web App开发 存储 前端开发
浏览器之性能指标_FCP(一)
浏览器之性能指标_FCP
150 0
|
25天前
|
JSON 移动开发 JavaScript
在浏览器执行js脚本的两种方式
【10月更文挑战第20天】本文介绍了在浏览器中执行HTTP请求的两种方式:`fetch`和`XMLHttpRequest`。`fetch`支持GET和POST请求,返回Promise对象,可以方便地处理异步操作。`XMLHttpRequest`则通过回调函数处理请求结果,适用于需要兼容旧浏览器的场景。文中还提供了具体的代码示例。
在浏览器执行js脚本的两种方式