srcset 与 sizes
srcset 和 sizes 是 HTML5 为响应式图片引入的两个属性,它们让浏览器能够根据设备屏幕宽度和像素密度,自动选择最合适的图片资源。本节将深入讲解这两个属性的语法、描述符类型以及实际配置方法。
前置知识
阅读本节前,建议先了解:图片尺寸与响应式图片
基础概念
在响应式设计中,不同设备可能需要不同尺寸或分辨率的图片。为手机用户提供一张 1920px 宽的大图是浪费带宽,而为桌面显示器提供 320px 的小图又会导致模糊。
srcset 属性允许你为 <img> 提供一组候选图片,浏览器根据屏幕条件自动选择最合适的版本。sizes 属性则告诉浏览器图片在不同屏幕宽度下的预期显示尺寸,帮助浏览器做出更精确的选择。
这两个属性可以独立使用,也可以配合使用以获得最佳效果。
语法
srcset 属性语法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>srcset 属性</title>
</head>
<body>
<h1>srcset 属性</h1>
<!-- 像素密度描述符(x):适用于固定宽度布局 -->
<img src="photo.jpg"
srcset="photo-1x.jpg 1x,
photo-2x.jpg 2x"
alt="使用像素密度描述符的图片">
<br>
<!-- 宽度描述符(w):适用于响应式布局 -->
<img src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w"
alt="使用宽度描述符的图片">
</body>
</html>sizes 属性语法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>sizes 属性</title>
</head>
<body>
<h1>sizes 属性</h1>
<!-- sizes 告诉浏览器在不同条件下的预期显示宽度 -->
<img src="photo-default.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w"
sizes="(max-width: 480px) 100vw,
(max-width: 900px) 50vw,
400px"
alt="配合 sizes 的响应式图片">
</body>
</html>详细说明
像素密度描述符(x 描述符)
像素密度描述符以 x 为单位,表示设备的像素密度(DPR,Device Pixel Ratio):
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>像素密度描述符</title>
<style>
.avatar {
width: 64px;
height: 64px;
border-radius: 50%;
}
</style>
</head>
<body>
<h1>像素密度描述符</h1>
<!-- 普通屏幕加载小图,高清屏幕加载大图 -->
<img class="avatar"
src="avatar-64.jpg"
srcset="avatar-64.jpg 1x,
avatar-128.jpg 2x,
avatar-192.jpg 3x"
alt="用户头像">
<p>
当设备像素比(DPR)为 1 时,加载 64x64 的图片;
DPR 为 2 时(如 Retina 屏幕),加载 128x128 的图片;
DPR 为 3 时,加载 192x192 的图片。
</p>
</body>
</html>| 描述符 | 含义 | 适用场景 |
|---|---|---|
1x | 1 倍像素密度(普通屏幕) | 基准图片 |
2x | 2 倍像素密度(Retina) | 高清屏幕 |
3x | 3 倍像素密度 | 超高清屏幕 |
宽度描述符(w 描述符)
宽度描述符以 w 为单位,表示图片的实际文件宽度:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>宽度描述符</title>
</head>
<body>
<h1>宽度描述符</h1>
<!-- 宽度描述符需要配合 sizes 属性使用 -->
<img src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w,
photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 75vw,
600px"
alt="使用宽度描述符的响应式图片"
width="1600" height="1067">
</body>
</html>浏览器选择逻辑
- 浏览器根据当前视口宽度和
sizes条件,计算出图片需要的显示宽度 - 将显示宽度乘以设备像素比,得到图片的有效像素宽度
- 在
srcset中选择大于等于该宽度且最接近的图片版本
x 描述符 vs w 描述符
| 对比项 | x 描述符 | w 描述符 |
|---|---|---|
| 单位 | 倍数(1x/2x/3x) | 像素宽度(400w/800w) |
| 是否需要 sizes | 不需要 | 需要 |
| 适用场景 | 固定宽度区域 | 响应式布局 |
| 灵活性 | 较低 | 较高 |
| 兼容性 | 所有现代浏览器 | 所有现代浏览器 |
sizes 属性的媒体条件
sizes 属性由一个或多个媒体条件 + 图片预期宽度组成:
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sizes 条件</title>
</head>
<body>
<h1>sizes 属性的媒体条件</h1>
<!-- 多条件匹配:从上到下评估,第一个匹配的条件生效 -->
<img src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w"
sizes="(max-width: 360px) 100vw,
(max-width: 768px) 80vw,
(max-width: 1200px) 50vw,
600px"
alt="多条件 sizes 响应式图片"
width="1200" height="800">
<p>常见 sizes 值速记:</p>
<ul>
<li><code>100vw</code>:图片占满整个视口宽度</li>
<li><code>50vw</code>:图片占视口宽度的一半</li>
<li><code>calc(100vw - 40px)</code>:视口宽度减去边距</li>
<li><code>600px</code>:固定 600px 宽度</li>
</ul>
</body>
</html>同时使用 x 和 w 描述符
不要混用描述符
一个 srcset 中只能使用一种描述符类型,要么全部用 x,要么全部用 w,不能混用。
html
<!-- 错误!混用 x 和 w 描述符 -->
<!-- <img srcset="photo-400.jpg 400w, photo-2x.jpg 2x" alt="错误"> -->
<!-- 正确:统一使用 w 描述符 -->
<img srcset="photo-400.jpg 400w, photo-800.jpg 800w" alt="正确">
<!-- 正确:统一使用 x 描述符 -->
<img srcset="photo.jpg 1x, photo-2x.jpg 2x" alt="正确">实战示例
响应式文章配图
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>响应式文章配图</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
line-height: 1.8;
}
article img {
width: 100%;
height: auto;
border-radius: 8px;
}
article figcaption {
text-align: center;
color: #888;
font-size: 14px;
margin-top: 8px;
}
</style>
</head>
<body>
<article>
<h1>为什么选择响应式图片</h1>
<p>在当今多设备时代,响应式图片是提升用户体验和网站性能的关键技术。</p>
<figure>
<img src="responsive-800.jpg"
srcset="responsive-400.jpg 400w,
responsive-800.jpg 800w,
responsive-1200.jpg 1200w"
sizes="100vw"
alt="不同设备上显示同一网站的对比图,从手机到桌面"
width="1200" height="675"
loading="lazy">
<figcaption>图 1:同一个网站在不同设备上的显示效果</figcaption>
</figure>
<p>
根据分析,移动端流量已占全球互联网流量的 60% 以上。
使用 srcset 和 sizes 可以为不同设备提供恰当大小的图片,
减少不必要的带宽消耗。
</p>
<figure>
<img src="bandwidth-chart-800.jpg"
srcset="bandwidth-chart-400.jpg 400w,
bandwidth-chart-800.jpg 800w"
sizes="(max-width: 600px) 100vw, 800px"
alt="移动端和桌面端带宽消耗对比柱状图"
width="800" height="450"
loading="lazy">
<figcaption>图 2:响应式图片可减少 40~60% 的移动端图片带宽</figcaption>
</figure>
</article>
</body>
</html>注意事项
srcset中不能混用x和w描述符- 使用
w描述符时建议搭配sizes属性,否则浏览器默认图片占满视口 sizes的最后一个值是默认值(无媒体条件),必须提供sizes只影响浏览器选择哪个候选图片,不影响图片的 CSS 显示尺寸- 图片的 CSS 显示尺寸仍由样式表控制
srcset中的src属性是回退方案,不支持 srcset 的浏览器会使用 src
最佳实践
- 根据布局类型选择描述符:固定宽度用
x,响应式布局用w - 准备 3~4 个不同尺寸的候选图片,覆盖从手机到桌面
- 始终提供
src属性作为回退 - 设置 HTML
width/height防止 CLS - 使用真实的图片文件,不要只准备一个版本然后在 HTML 中"假装"有多个
sizes的值应与实际 CSS 布局一致,否则浏览器选择会不准确- 可以使用
<picture>元素实现更复杂的响应式图片逻辑
下一节
继续学习:picture 与 source