响应式图片img标签中srcset和sizes的使用

2,071 阅读4分钟

背景

日常开发中,我们使用固定大小的图片,但是对于不同的设备,设备像素比(dpr)的不同,图片的清晰度会受到影响。

我们可以在img标签中使用srcset和sizes属性来解决这个问题。

1. 不同dpr下图片显示

我们先看一个案例,在正常情况下,我们固定图片的宽高,通过修改设备的dpr看看图片显示问题。

具体步骤如下:

  1. 新建一个index.html,设置图片宽高为150px,图片使用宽高为150,(这里图片可以根据最后的数字生成对应大小的图片宽高)

index.html:

<style>
img{
  width: 150px;
  height: 150px;
}
</style>

<body>
  <img src="https://picsum.photos/id/88/150" alt=""/>
</body>
</html>
  1. dpr为1时,正常显示:

image.png

  1. 将浏览器放大5倍,dpr此时为5(可以使用window.devicePixelRatio查看dpr),图片出现失真情况

image.png image.png

image.png

这里我们需要理解一下下面的概念:

  • CSS 尺寸
    在 HTML 或 CSS 中指定的图片逻辑宽度。通过 widthsizes 属性定义的值。

  • 设备像素比 (DPR)
    设备像素比是设备物理像素与 CSS 像素的比值:

    • DPR = 1:每个 CSS 像素映射到一个物理像素。
    • DPR = 2:每个 CSS 像素映射到 2×2 个物理像素。
  • 实际像素尺寸
    为了确保图片在高 DPR 屏幕上依然清晰,浏览器会请求更高分辨率的图片,实际尺寸公式计算:

    图片的尺寸=css尺寸设备像素比dpr图片的尺寸 = css尺寸 * 设备像素比dpr

浏览器请求对应的图片大小是需要考虑设置的css大小dpr的大小

2. srcset属性

srcset 的值是一个字符串,用来定义一个或多个图像候选地址,以 , 分割,每个候选地址将在特定条件下使用。

案例:当我们的宽度固定为150px,我们修改设备的dpr,会使图片拉伸模糊,通过设置srcset这个值,可以将不同dpr,找到合适的图片显示。

具体步骤:

  1. srcset属性设置标准像素密度 (2x 3x 4x)下使用的图像版本,默认就是1x可以省略不写
<img src="https://picsum.photos/id/88/150" srcset="
  https://picsum.photos/id/88/300 2x,
  https://picsum.photos/id/88/450 3x,
  https://picsum.photos/id/88/600 4x" alt="" />

  1. 当放大两倍,此时dpr为2,找到2x对应图片

image.png

  1. 如果放大5倍,此时dpr为5,没有设置对应的图片,会选择适合的4x图片

image.png

上面案例是我们固定图片的宽度,当我们使用响应式宽度,图片是如何设置呢?就需要使用我们的sizes属性。

3. sizes属性

sizes 允许您为每个媒体条件指定图像的布局宽度。在布局状态更改以匹配不同介质条件时自动选择不同图像(甚至是不同方向或长宽比的图像)的能力。

案例:我们将图片的宽高设置为50vw 50vh,根据视口变化选择不同的图片。

  • dpr为1,变化视口宽度
  • dpr为2,变化视口宽度

3.1 未设置前

image.png

3.2 设置sizes属性

具体步骤如下:

  1. srcset中设置对应宽度图片,sizes中使用(max-width)进行匹配
img {
  width: 50vw;
  height: 50vw;
}

<img src="https://picsum.photos/id/88/150" srcset="
  https://picsum.photos/id/88/150 150w,
  https://picsum.photos/id/88/300 300w,
  https://picsum.photos/id/88/600 600w,
  https://picsum.photos/id/88/900 900w,
  https://picsum.photos/id/88/1200 1200w" sizes="
  (max-width: 300px) 150px,
  (max-width: 600px) 300px,
  (max-width: 900px) 450px,
  (max-width: 1200px) 600px,
  1200px" alt="" />

可以简写为:

<img src="https://picsum.photos/id/88/150" srcset="
  https://picsum.photos/id/88/300 300w,
  https://picsum.photos/id/88/600 600w,
  https://picsum.photos/id/88/900 900w,
  https://picsum.photos/id/88/1200 1200w" sizes="50vw" alt="" />
  1. dpr为1时,可以看到在因为不同的dpr对应的匹配是不同的。

dpr1-ezgif.com-video-to-gif-converter.gif

浏览器根据视口宽度匹配 sizes 属性中的条件:

  • (max-width: 300px) 150px: 如果视口宽度 ≤ 300px,图片理想显示宽度是 150px。
  • (max-width: 600px) 300px: 如果视口宽度 ≤ 600px,图片理想显示宽度是 300px。
  • (max-width: 900px) 450px: 如果视口宽度 ≤ 900px,图片理想显示宽度是 450px。
  • (max-width: 1200px) 600px: 如果视口宽度 ≤ 1200px,图片理想显示宽度是 600px。
  • 如果视口宽度 > 1200px,则使用默认值 1200px
  1. dpr为2时

dpr2-ezgif.com-video-to-gif-converter.gif

可以看到,视口宽度小于150,也显示300,没有显示150。

因为在高 DPR(设备像素比)环境下,浏览器会选择更高分辨率的图片来确保显示清晰度,不是严格按照视口宽度匹配。

4. 总结

总结一下:图片需要适应不同设备,我们可以使用 srcsetsizes 来实现图片高清显示。需要注意是某种情况下并不是严格按照规则进行匹配。

如有错误,请指正O^O!