响应式图片(picture、srcset、source 等)综合指南
响应式图片的规范经历了多年的讨论和多次迭代,而且涉及的领域非常广泛,因此语法也比较繁杂。在本文中,我将尝试让您全面了解创建响应式图片的所有不同方法。
我将把它分为三个部分:
为什么
正如本系列第一部分所述,大尺寸图片会严重拖慢网站速度。我们已经通过压缩图片来减小文件大小,但在手机上,图片分辨率仍然与桌面端相同。响应式图片则可以根据屏幕尺寸、屏幕分辨率或图片宽度来提供不同分辨率的图片。
句法
有很多方法可以让图片具有响应式布局,要了解它们的工作原理,我们需要了解一些新的语法:
让我们从一个例子开始,逐一讲解语法各个部分的作用。
<img src="file-200px.jpg"
alt="some file"
srcset="file-200px.jpg 1x,
file-400px.jpg 2x,
file-600px.jpg 3x>
来源
src="file-200px.jpg"
这决定了图像的来源。它也被用作所有不支持 srcset 的浏览器的来源。
srcset
srcset="file-200px.jpg 1x,
file-400px.jpg 2x,
file-600px.jpg 3x
Srcset它由一个或多个图像候选对象组成。候选对象之间用逗号分隔,每个候选对象包含一个图像 URL 和一个可选条件。如果满足该条件,则会使用候选图像源而不是默认图像源。
条件
1倍、2倍等(显示密度)
随着高密度屏幕的引入,CSS 必须区分作为测量单位的像素和屏幕上的实际像素,以避免布局在高分辨率屏幕上显得过小。
例如,在 iPhone 11 上,每个 CSS 像素实际上是 2 个设备像素的大小。这意味着设备像素比为2x。
srcset="file-200px.jpg 1x,
file-400px.jpg 2x,
file-600px.jpg 3x"
因此,我们的例子可以实现的是,为使用高密度屏幕的用户提供更高分辨率的图像,以便他们充分利用高分辨率的优势。同时,我们也确保使用低密度屏幕的用户不会浪费不必要的数据。
用文字翻译以上句法的意思是
- 如果用户设备的像素比为 1x,则为其提供服务。
file-200px.jpg - 如果用户设备的像素比为 2x,则为其提供服务。
file-400px.jpg - ETC
200瓦、400瓦等(宽度描述符)
srcset="file-200px.jpg 200w,
file-400px.jpg 400w,
file-600px.jpg 600w"
宽度描述符描述的是文件的分辨率,也就是你在图片编辑器或其他软件中打开图片时看到的实际像素宽度。浏览器会根据这个宽度来决定使用哪个图片源。但是,仅仅知道图片分辨率不足以让浏览器做出决定。
当浏览器开始下载资源时,它并不知道图片元素最终会在页面上占据多大的宽度,所以要使用宽度描述符,我们必须告诉浏览器图片的实际尺寸!宽度描述符必须与 `sizes` 属性一起使用,因此完整的语法如下所示:
srcset="file-200px.jpg 200w,
file-400px.jpg 400w,
file-600px.jpg 600w"
sizes="(min-width: 900px) 700px,
(min-width: 400px) 80vw,
100vw"
这种语法乍一看可能令人望而生畏,但实际上非常简单明了,我们通过指定尺寸所做的只是告诉浏览器:
- “当屏幕宽度超过 900px 时,图像将填充的插槽宽度为 700px。”
- “当屏幕宽度超过 400px 时,图像将填充的插槽宽度为 80vw。”
- “当所有媒体条件均不成立时,图像将填充的插槽宽度为 100vw”
您可以使用绝对单位(如px或em )或相对于视口 ( vw )的长度,但不能使用百分比。
浏览器将使用这些尺寸来:
- 看看它的设备宽度
- 找出尺寸列表中第一个符合条件的介质类型。
- 查看分配给该媒体查询的插槽大小
- 加载 srcset 列表中与所选插槽尺寸最匹配的图像。
图片标签
如果格式不正确,上面的语法很难记住,而且功能也比较有限。幸运的是,还有另一种方法。
<picture>
<source srcset="example-200px.jpg" media="(min-width: 800px)">
<source srcset="example.webp" type="image/webp">
<img src="example.jpg" />
</picture>
`<picture>` 标签接受一个 ` img<img>` 元素和零个或多个 ` source<img>` 标签。可以这样理解:`<picture>`picture元素会赋予img其内部元素不同的属性sources。不支持 `<picture>`picture或 `<img>`source标签的浏览器会直接忽略 `<picture>` 标签,只渲染img其内部的 `<img>` 元素。
源标签
您可能已经见过 `<script>` 标签内包含 `<source>` 标签的video情况。在 `<script>` 标签内,picture它可以用来实现多种功能:
使用现代图像格式
在上面的例子中,我们使用了<source srcset="example.webp" type="image/webp">WebP。WebP 是一种现代图像格式,我在本系列的第一部分中已经介绍过。由于浏览器对 WebP 的支持还不完善,我们不能只使用 WebP 作为图像的源,但source可以通过 `<img>` 标签指定源webp,这样所有支持 WebP 的浏览器都会使用它。请务必将源设置type为 `<img>` image/webp,以便浏览器可以读取它。
根据视口大小更改 src 属性
<picture>
<source media="(max-width: 800px)" srcset="example-small.jpg">
<source media="(max-width: 1200px)" srcset="example-large.jpg">
<img src="example-default.jpg">
</picture>
当视口尺寸小于 800 像素时,此语法的含义显而易见:它会显示图像的缩小版本。除了提供低分辨率版本外,您还可以在较小的屏幕上提供完全不同的图像。如果您想在较小的屏幕上显示图像的低分辨率版本或放大版本,这将非常有用。
使用 srcset 和 size
<source srcset="file-200px.jpg 200w,
file-400px.jpg 400w,
file-600px.jpg 600w">
就像常规标签一样,源也可以支持 srcset 和 sizes 标签img。
如何
你的方法应该始终取决于你的具体使用场景。我通常会使用 `<picture>` 标签,因为它支持 webp 格式,而且最为灵活。在使用 Vue、React、Svelte 等框架时,我建议创建一个可复用的组件,并将其与你的后端架构集成。例如,在 React 中,它可以像这样:
<MyPictureComponent
sizes={{
default: allSources.medium,
mobile: allSources.small,
desktop: allSources.large
}}
/>
这将渲染出类似这样的内容:
<picture>
<source media="(max-width: 800px)" srcset={sizes.small.webp} type="image/webp" />
<source media="(max-width: 1200px)" srcset={sizes.large.webp} type="image/webp" />
<source media="(max-width: 800px)" srcset={sizes.small.jpg} />
<source media="(max-width: 1200px)" srcset={sizes.large.jpg} />
<img src={sizes.default.jpg} />
</picture>
这样一来,webp 就成为默认处理方式,而且整个过程也更简洁一些。
你有没有关于响应式图片的优秀抽象概念?请告诉我👇
概括
- srcset 属性允许你通过提供备选来源和条件列表来增强 img 标签的功能。
- 条件可根据屏幕密度和图像尺寸而定。
- picture 标签允许您为图像指定多个来源,以便在不同的屏幕尺寸上指定不同的图像,并使用现代图像格式以及备用格式。
