优化 Cumulative Layout Shift 累积布局偏移
"我正准备点那里!为什么移走了??"
布局偏移可能会分散用户的注意力。想象一下,您已经开始阅读一篇文章,可是页面上的元素突然位移,让您措手不及,于是您不得不再次找到先前阅读的位置。这在网络上十分常见,包括在阅读新闻或尝试单击"搜索"或"添加到购物车"按钮时。这种体验在视觉上十分扎眼且令人郁闷。这些情况通常是由于另一个元素被突然添加到页面上或是突然调整了大小,使可见元素被迫移动位置而导致的。
累积布局偏移 (CLS):核心 Web 指标中的一项指标,通过计算未在用户输入 500 毫秒内发生的布局偏移的偏移分数总和来测量内容的不稳定性。该项指标查看可视区域中可见内容的位移量以及受影响元素的位移距离。
在本篇指南中,我们将介绍针对布局偏移常见成因的优化方式。
CLS 较差的最常见原因为:
无尺寸的图像
无尺寸的广告、嵌入和 iframe
动态注入的内容
导致不可见文本闪烁 (FOIT)/无样式文本闪烁 (FOUT) 的网络字体
在更新 DOM 之前等待网络响应的操作
无尺寸的图像 ? #
概述:始终在您的图像和视频元素上包含width和height属性。或者通过使用CSS 长宽比容器预留所需的空间。这种方法可以确保浏览器能够在加载图像期间在文档中分配正确的空间大小。
历史 #
在网络发展的早期阶段,开发者会在他们的<img>标签中加入width和height属性,从而确保浏览器在开始获取图像前会在页面上预先分配足够的空间。这样可以最大限度地减少回流和重排。
<img src="puppy.jpg" width="640" height="360" alt="小狗与气球" />
您可能会注意到,上方的width和height不包括单位。这些"像素"尺寸可以确保一块 640x360 的保留区域。无论图像的真实尺寸是否匹配,该图像都会被拉伸成保留区域的大小。
响应式网页设计得到引入后,开发者开始省略width和height,并取而代之开始使用 CSS 来调整图像大小:
img {
width: 100%; /* or max-width: 100%; */
height: auto;
}
这种方法的一个缺点是,只有在图像开始下载且浏览器可以确定其尺寸后才能为图像分配空间。随着图像的加载,页面会随着每个图像出现在屏幕上而进行重排,因此导致文本常常突然出现在屏幕上。这与良好的用户体验相距甚远。
这种情况下就需要用到长宽比。图像的长宽比是图像宽度与高度的比例。我们通常用由冒号分隔的两个数字来表示长宽比(例如 16:9 或 4:3)。x:y 的长宽比表示图像的宽度为 x 单位,高度为 y 单位。
也就是说,如果我们知道其中一个维度,就可以确定另一个维度。对于 16:9 的长宽比:
如果 puppy.jpg 的高度为 360px,则宽度为 360 x (16 / 9) = 640px
如果 puppy.jpg 的宽度为 640px,则高度为 640 x (9 / 16) = 360px
在知道长宽比的情况下,浏览器就能够进行计算,并为高度和其关联区域预留足够的空间。
现代最佳实践 #
现代浏览器目前会根据图像的宽度和高度属性设置图像的默认长宽比,因此,通过设置这些属性来防止布局偏移是非常有价值的。感谢 CSS 工作组的努力,开发者只需要照常设置width和height即可:
<!-- set a 640:360 i.e a 16:9 - aspect ratio -->
<img src="puppy.jpg" width="640" height="360" alt="小狗与气球" />
……而且所有浏览器的UA 样式表都会根据元素现有的width和height属性添加默认长宽比:
img {
aspect-ratio: attr(width) / attr(height);
}
提示:如果您很难理解长宽比,还可以使用便捷的计算器来帮助计算。
上述针对图像长宽比的变化已经在 Firefox 和 Chromium 中得到应用,并将在 WebKit (Safari) 中进行应用。
如需深入了解长宽比并对响应式图像展开进一步思考,请参阅使用媒体长宽比实现无卡顿页面加载。
如果您的图像在容器中,您可以使用 CSS 将图像大小调整为该容器的宽度。我们需要设置height: auto;来避免图像高度为某个固定值(例如360px )。
img {
height: auto;
width: 100%;
}
如何处理响应式图像?
处理响应式图像时,srcset定义了允许浏览器选择的图像以及每个图像的大小。为了保证<img>的宽度和高度属性可以进行设置,每个图像都应该采用相同的长宽比。
<img
width="1000"
height="1000"
src="puppy-1000.jpg"
srcset="puppy-1000.jpg 1000w, puppy-2000.jpg 2000w, puppy-3000.jpg 3000w"
alt="小狗与气球"
/>
如何处理美术设计?
页面可能会想要在窄可视区域中包含一张剪裁后的图像,并在桌面上显示完整图像。
<picture>
<source media="(max-width: 799px)" srcset="puppy-480w-cropped.jpg" />
<source media="(min-width: 800px)" srcset="puppy-800w.jpg" />
<img src="puppy-800w.jpg" alt="小狗与气球" />
</picture>