优化图片元素的LCP(译)
原文链接:www.smashingmagazine.com/2023/01/opt…
Largest Contentful Paint(或简称LCP)是一个主要网页性能度量的关键指标,它对于许多Web开发者来说是一个新概念,因为它最近才成为一个排名因素。在这篇文章中,Eloïse Martin提供了如何集成和优化LCP图像的最佳实践。
Largest Contentful Paint(或简称LCP) 是核心Web要素中的三个度量之一。这些度量是Google用于评估用户体验的质量。LCP测量的是浏览器加载视口中主要内容所需的时间。
因为LCP最近才成为一个排名因素,所以这个重要的网络性能关键绩效指标对许多Web开发者来说还是一个新概念。当LCP元素是一张图片时,优化变得特别棘手。
为了解决这个问题,我将提供一个关于集成和优化LCP图像的最佳实践。此次时间包含以下内容:
- 如何通过使用
<img>
标签以及正确调整图像尺寸来改善LCP资源加载的时间。 - 关于浏览器对于
<img>
标签及其属性的行为的一些解释,以便大家能够真正理解并正确集成LCP图像。 - 如何改善LCP资源加载延迟时间。
下面的介绍我们将通过一个示例来进行说明。文章中在Codepen演示中使用的图片将集成TwicPics,以节省创建时间并加快LCP指标的优化。
注意:其他LCP子部分包括“首字节时间”和“元素渲染延迟”,这些内容不在本文涵盖范围内。要了解更多关于四个LCP子部分及它们之间关系的信息,请阅读Philip Walton和Barry Pollard的文章“优化最大内容绘制”。如果您想要找出如何在您的网页上识别LCP元素,可以查看Laurent Cazanove的这篇指南。
通过使用 <img>
标签来改善LCP资源加载时间
这里的目标是尽量减少LCP图像的加载时间,同时不影响其视觉质量。要成功执行此操作,其中一个关键点是让浏览器选择最适合的图像版本。
与通过src
属性声明一个单一的图像文件,其尺寸在任何设备上都相同不同,我们需要让浏览器选择最适合每个上下文的图像文件。这种方法允许为较小设备上的用户下载尺寸较小的图像。这样,图像加载速度更快,您的网站将获得更好的LCP评分。
为了实现这一点,我们需要使用 <img>
标签及其 srcset
和 sizes
属性提供浏览器所需的信息:
srcset
属性将浏览器引导到图像文件列表,并提供它们的固有宽度描述。sizes
属性告诉浏览器图像的预期显示宽度。它可以与CSS媒体查询结合使用,以选择适合屏幕宽度的图像。
注意: 可以使用 <picture>
标签代替 <img>
标签,以允许浏览器根据设备特性,如视口宽度或图像格式兼容性,加载不同的图像。为简单起见,在我们的示例中,我们将仅使用 <img>
标签。
<img>
标签的 srcset
属性
<img>
标签的 srcset
属性包含了一个图像文件列表以及它们的固有宽度。浏览器使用这个列表来选择它认为最适合用户上下文的图像。
这使得 srcset
属性成为优化LCP图像的第一步。
<img srcset="" src="" alt="" />
要声明这个图像列表,建议采用移动优先的方法。我们使用 src
属性将最小的图像声明为默认选项,然后在 srcset
属性中再次声明它,接着是较大尺寸的变体。
每个图像的固有宽度,以像素为单位,使用单位"w"("w"代表"width",即宽度)来表示:
<img
src="image-300.png"
srcset="
image-300.png 300w,
image-900.png 900w,
image-1800.png 1800w"
alt="Image description"
/>
上面的示例定义了三张图片(image-300.png、image-900.png 和 image-1800.png),用逗号分隔,固有宽度分别为 300、900 和 1800 像素。为了遵循移动优先方法,这里的默认图像是 image-300.png,在 src 和 srcset 属性中都有定义。
注意: 在使用 srcset 属性时,保留 src 属性很重要,这样浏览器知道哪个是默认图像,并确保在不支持 srcset 属性的浏览器上可以正确显示图片。
注意: 还可以使用 srcset 属性来声明图像的设备像素比(Device Pixel Ratio,DPR),而不是它们的固有宽度;本文不讨论这种方法。
了解用户上下文后,浏览器现在可以从在 srcset 属性声明的列表中选择要加载的图像。
为了避免出现意料之外的结果,我们需要了解浏览器如何选择最合适的图像:
- 在
srcset
属性中,浏览器总是根据视口大小选择图像;它忽略图像的显示尺寸。因此,我们的CSS样式和媒体查询对其选择没有影响。在定义图像列表时,我们还需要考虑移动设备和平板电脑的横向方向。 - 默认情况下(未指定
size
属性),浏览器选择图像是假定它占据视口宽度的100% 。 - 由于浏览器了解设备的分辨率,它还会在计算中考虑设备像素比(Device Pixel Ratio,DPR) 。因此,为了优化LCP图像,还需要为每个DPR定义一个变体。
基于这些行为,浏览器根据视口宽度选择图像的默认公式是:
视口宽度 x 100% x DPR
注意:当列表中没有任何图像与计算匹配时,浏览器将选择最接近的匹配项。如果出现多个最近的匹配项,浏览器将选择较大的图像。
让我们通过一个示例来说明浏览器的行为,使用我们之前的代码:
<img
src="image-300.png"
srcset="
image-300.png 300w,
image-900.png 900w,
image-1800.png 1800w"
alt="Image description"
/>
示例代码:Codepen demo 1.
注意: 在浏览器的开发工具中,打开 Network > Img 选项卡,可以查看浏览器根据每个视口和DPR选择的图像。
在这个演示中,图像在所有设备上都以固定宽度的280px显示。但在宽度为900px、DPR为1的屏幕上,浏览器将在 srcset
属性的图像列表中寻找一个图像,满足以下条件:
900px(视口宽度) x 100%(默认情况下图像占据的视口宽度) x 1(DPR)
在这种情况下,浏览器会查找一个宽度为900px的图像。
在我们的示例中,尽管图像的显示宽度为280px,但仍会加载具有固有宽度为900px的图像。
从这个示例中,我们可以看出在我们的 srcset
属性中声明的图像并不适应所有显示宽度为 280px
的设备。
浏览器使用了公式viewportWidth x 100% x DPR
来选择要加载的图像,我们还可以使用一个更简
单的公式来生成在 srcset
属性中声明的不同图像:
imageRenderedSize x DPR
考虑到我们第一个演示中的DPRs 1、2和3,我们需要创建和定义以下三个图像:
- DPR 1:
280 x 1
=> 一个宽度为280像素
的图像; - DPR 2:
280 x 2
=> 一个宽度为560像素
的图像; - DPR 3:
280 x 3
=> 一个宽度为840像素
的图像。
最后,更新我们的代码:
<img
src="image-280.png"
srcset="
image-280.png 280w,
image-560.png 560w,
image-840.png 840w"
alt="Image description"
/>
示例代码:Codepen demo 2
然而,更新后的代码还没有完全针对所有设备进行优化。
实际上,对于一个具有1024px
视口和DPR 2的笔记本设备,最佳图像应该是固有宽度为560px
(imageRenderedSize x DPR
= 280 x 2
= 560
)。但使用这段代码,浏览器会加载一个尺寸为1024 x 100% x 2
,也就是2048px
的图像,而这个尺寸在 srcset
属性中是不存在的。
让我们看看 sizes
属性如何帮助我们解决这个问题。
<img>
标签的 sizes
属性
sizes
属性为开发者提供了对浏览器行为的额外控制,防止浏览器默认图像占据视口的100%。这有助于确保加载最佳图像,从而优化您的LCP指标。
<img srcset="" sizes="" src="" alt="" />
注意:当图像实际上占据视口的100%时,sizes
属性是不必要的。
要分配 sizes
属性的值,我们可以使用以下方法:
- 将图像宽度定义为视口宽度的百分比,例如,当图像是响应式的时候(例如,当CSS的
width
属性被定义为百分比时),可以使用sizes="50vw"
。 - 当图像具有固定的显示宽度而不考虑用户设备时,可以定义图像的宽度为像素,例如
sizes="500px"
。 - 使用一个或多个媒体查询,让浏览器根据不同的视口选择最佳图像,例如
sizes="(min-width: 1024px) 800px, (min-width: 768px) 80vw, 100vw"
(当没有应用媒体查询时,默认值是100vw
)。
让我们更新我们的代码示例:
<img
src="image-280.png"
srcset="
image-280.png 280w,
image-480.png 480w,
image-560.png 560w,
image-840.png 840w,
image-960.png 960w,
image-1440.png 1440w"
sizes="(min-width: 768px) 480px, 87.5vw"
alt="Image description"
/>
注意:要知道图像占据百分比视口宽度,应用计算公式(imageRenderedSize / viewportWidth) x 100
,例如,(280 / 320) x 100
= 视口宽度的 87.5%(87.5vw
)。
示例代码:Codepen demo 3
现在,使用我们第三个演示的源代码,无论DPR如何,浏览器都可以加载完美的图像:
- 对于视口宽度为
320px
的显示宽度为280px
的图片(占视口的87.5%)。 - 对于最小宽度为
768px
768px视口的设备上显示宽度为480px
的图片。
在这个阶段,如果通过<img>
标签及其srcset
和sizes
属性正确进行了LCP图像的集成,LCP资源加载时间的优化应该是最佳的。
注意: 我们主要关注根据用户设备正确调整LCP图像的大小。为了使LCP评分及其“资源加载时间”真正达到最佳效果,我们还可以考虑使用现代图像格式压缩图像、设置远期缓存到期标头,甚至使用CDN来减少网络距离。
注意: 即使我们的LCP图像经过良好优化并在<img>
标签中正确集成,如果我们的页面包含渲染阻塞资源,如JavaScript文件,这仍然会是页面性能质量下降。请参考Philip Walton的演讲,了解如何消除延迟渲染不必要的元素。
接下来让我们看看如何通过减少加载时间进一步优化LCP评分。
优化LCP资源延迟加载
在本节中,我们继续在之前示例代码的基础上优化,以了解如何尽快加载LCP图像。
不要对LCP图像元素进行懒加载。
当用户问网站时,通常会通过懒加载技术延迟加载LCP图像,无论是通过原生的懒加载还是通过JavaScript库实现懒加载。但重要的是要注意,这种加载延迟会包含在LCP时间的计算中。
例如,使用懒加载JavaScript库,必须首先加载脚本才能加载最终的图像。这个额外的步骤会导致LCP资源加载方面的显著延迟。
换句话说,懒加载LCP图像会降低的LCP评分。
同样,在编写本文时,Google不考虑渐进加载或低质量图像占位符(LQIP)作为LCP的一部分。然而,关于LQIP的讨论正在进行中,所以情况可能会在未来发生变化。
使用优先提示
我们看到,LCP图像不能被懒加载。但是我们如何能够优先加载它呢?
为了管理页面的资源,浏览器本身会根据一系列参数中定义的优先级来应用加载顺序,其中包括资源的类型。
与渲染阻塞资源相比,图像具有较低的优先级。这不仅意味着资源以较低的优先级获取,还意味着获取实际上会被延迟,因为浏览器故意会最初延迟“低”优先级的资源,以便它们可以集中处理更关键的、通常是渲染阻塞的资源。
这意味着我们需要改变浏览器的默认加载顺序以及其对主要图像的行为,以使LCP图像不会被延迟,可以在HTML文档接收后尽快加载。
通过fetchpriority="high"
属性,我们可以修改这个加载优先级。
<img fetchpriority="high" src="" alt="">
让我们更新代码示例。只需将该属性添加到<img>
标签中,浏览器将根据在srcset
属性中声明的源自动确定图像的正确版本以进行优先处理:
<img fetchpriority="high"
src="image-280.png"
srcset="
image-280.png 280w,
image-480.png 480w,
image-560.png 560w,
image-840.png 840w,
image-960.png 960w,
image-1440.png 1440w"
sizes="(min-width: 768px) 480px, 87.5vw"
alt="Image description"
/>
示例代码:the final demo
注意: fetchpriority
属性也适用于<picture>
元素的<img>
标签。目前,它主要与Chromium兼容,预计在2023年初兼容Firefox。然而,请注意,即使浏览器不支持该属性,我们仍然可以使用fetchpriority
属性而不会产生任何负面影响:不支持的浏览器将简单地忽略该属性。
正如我们在演示中所示,<img>
标签及其src
和srcset
属性存在于初始HTML源代码中。这意味着在这里无需预加载LCP资源,因为浏览器的预加载扫描器可以发现它。
注意: 并非所有浏览器都支持响应式图像的预加载,例如Safari就不支持:确保不在<link>
元素上使用href
属性,以防止不支持的浏览器请求无用的图像。阅读这篇文章以了解更多信息,并查看何时需要预加载LCP资源。
在最后的演示中,浏览器不仅可以知道适用于视口宽度为320px
的设备和最小宽度为768px
的设备所需的最佳图像,还可以将其加载优先级与其他资源进行比较。作为开发者,本文中所说明的所有要点都是帮助您提高网站的LCP评分。
结论
总结一下,以下是优化LCP图像所需的步骤:
- 一旦为您的网站定义了页面模板,根据
imageRenderedSize x DPR
的公式为每个设备和每个DPR创建并存储所需的所有图像。为了简化此步骤,您可以使用TwicPics API从高质量的原始图像生成不同尺寸的多个版本。 - 使用
<img>
标签的srcset
属性,包括在步骤1中定义的图像列表,遵循移动优先的方法(记得将默认图像放在src
属性中)。 - 使用
<img>
标签的sizes
属性,结合需要的媒体查询,告诉浏览器根据不同设备上下文图像将占据的显示宽度:
-
- 如果图像是响应式的,请使用公式
(imageRenderedSize / viewportWidth) x 100
将其宽度定义为视口宽度的百分比。 - 如果图像适用于一系列视口宽度,请简单地以像素定义其宽度。
- 如果图像是响应式的,请使用公式
- 为进一步提高LCP评分,使用
fetchpriority="high"
属性优先提示来优先加载LCP图像。并且记住不要懒加载LCP图像资源!
更多关于SmashingMag的阅读材料
转载自:https://juejin.cn/post/7277917295272493096