来自电子邮件的释义问题
我刚刚阅读了您的文章 响应式图片:如果您只是更改分辨率,请使用 srcset。 在“响应式网站”时代,
srcset
在某些情况下无济于事。 例如,我有一个热门产品滑块。 在移动设备上,每个幻灯片一张图片,图片宽度为 320px。 在桌面设备上,每个幻灯片六张图片,每张图片宽度为 160px。 因此,桌面图片在桌面设备上更小,而不是更大。我该如何使用
srcset
处理这种情况?
我试图谨慎地选择这篇文章的标题:“如果您只是更改分辨率,请使用 srcset”。 在这种情况下,我们不仅在某些分辨率下更改图片的大小,而且在特定的断点处也会更改,这意味着我们还需要使用 sizes
属性才能充分利用响应式图片。 sizes
属性的全部工作就是根据我们的 CSS 告诉浏览器图片将显示的大小。
演示!调整宽度以查看它在“桌面”和“移动”视图之间交替显示。
查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的笔 响应式图片滑块。
如电子邮件中所述,“桌面”版本实际上呈现的图片大小(160px)小于“移动”版本(320px)。
我们还要考虑 2 倍显示屏。 为此,我们准备三个版本的每个图片
- 160px(适用于 1 倍桌面显示屏)
- 320px(适用于 2 倍桌面显示屏或 1 倍移动显示屏)
- 640px(适用于 2 倍移动显示屏)
使用 srcset
,看起来像这样
<img srcset="
food-big.jpg 640w,
foot-medium.jpg 320w,
food-small.jpg 160w"
/>
请注意,我们尚未使用 sizes
属性。 浏览器会假设您可能将此图片渲染为 100vw 宽。 这很不幸,因为浏览器可能会下载比需要的更大的图片,而这正是我们使用响应式图片想要解决的问题。

正是我们的 CSS 控制了这些图片的渲染大小。 事实上,在此演示中,我们有一个媒体查询,它说:“浏览器,仅在桌面显示屏上将图片渲染为 160px 宽”。
@media (min-width: 600px) {
.slider img {
width: 160px;
}
}
您可能会认为浏览器会知道这一点,它确实知道——它只需要先下载并解析 CSS。 浏览器希望比这更快地做出下载决策。 因此,让我们使用 sizes
属性告诉它。
<img srcset="
food-big.jpg 640w,
foot-medium.jpg 320w,
food-small.jpg 160w"
sizes="(min-width: 600px) 160px, 320px"
/>
也就是说,“好的,我们将在桌面上将此图片渲染为 160px 宽。 否则,让我们使用 320px 宽”。 使用它,我们可以看到浏览器做出了正确的选择

为了确保,这是一个窄视口(例如“移动”设备)

sizes
属性告诉浏览器我们打算在 320px 处渲染,并且我们使用的是 2 倍显示屏。这里还有更多细微差别
我向 Eric “Sizes 大师” Portis 展示了这个演示,他证实了所有这些,但还有一些特定于浏览器的补充。 我将总结一下(但请注意这篇博文的日期,因为这些东西往往会发生变化)
- Firefox 的行为完全如上所述。
- Chrome 也是如此,除了如果它在缓存中具有该版本,它将始终使用较大版本。 因此,如果它在缓存中具有 640px 版本,它知道它实际上只需要 320px 版本,但由于它在缓存中没有 320px 版本,因此它将改为使用 640px 版本。
- Safari 也是如此,除了在做出选择后,它永远不会更改(例如,如果您调整浏览器窗口大小)。
- 关于
srcset
的一个有趣之处在于,规范允许它以任何方式做出选择,也许使用网络条件来决定。 大多数浏览器还没有这样做,除了 Chrome,如果 HTML 文档上有一个Save-Data
标头,它会下载最小的资源。 - Joe McGill 还指出:“对于不支持
srcset
中w
描述符的旧版 iOS 设备,将使用列表中的第一个源项,因此如果您支持旧版 iOS 设备,则可能需要以首选的默认大小开头”。 换句话说,这些旧版 iOS 设备可能支持响应式图片的早期语法,但仅支持x
描述符(如big-image.jpg 2x
),因此也许可以将一个好的默认图片指定为srcset
中的第一个。
查看 Eric 的分支可能会有所帮助,以便更轻松地查看下载的内容
查看 CodePen 上 Eric Portis (@eeeps) 编写的笔 响应式图片滑块。
随机笔记
- 我从 Unsplash 获取了这些食物照片。
- 我将它们上传到 Cloudinary,以便我可以使用 URL 参数调整它们的大小,而不必自己处理。
- 它们都是正方形,不是因为我这样下载的,而是因为我在 CSS 中调整了它们的大小,并使用
object-fit
防止了挤压。 这意味着正在下载不需要的图片数据,因此我应该自己裁剪它们或使用 Cloudinary URL 参数 来做到这一点。 - 我在演示中使用了 Pug HTML 预处理器,只是为了减少代码重复。
这更容易查看
img(srcset=`
${img_base}w_640${img_1} 640w,
${img_base}w_320${img_1} 320w,
${img_base}w_160${img_1} 160w,
` sizes=sizes)
…而不是输出
<img srcset="
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_640/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 640w,
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_320/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 320w,
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_160/v1531407936/robin-stickel-82145-unsplash_qnexwz.jpg 160w,
" sizes="(min-width: 600px) 160px, 320px"/><img srcset="
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_640/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg 640w,
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_320/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg 320w,
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_160/v1531407936/cel-lisboa-60315-unsplash_qsji9j.jpg.jpg 160w,
" sizes="(min-width: 600px) 160px, 320px"/><img srcset="
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_640/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg 640w,
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_320/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg 320w,
https://res.cloudinary.com/css-tricks/image/upload/c_scale,f_auto,q_auto,w_160/v1531407936/charles-deluvio-466056-unsplash_ocd3dh.jpg.jpg 160w,
" sizes="(min-width: 600px) 160px, 320px"/>
一个很棒的代码检查工具,可以检查 sizes 属性是否使用了正确的值。
https://github.com/ausi/respimagelint
我一直都在使用它。
更改分辨率很重要
嗨,Chris,感谢您撰写这篇很棒的文章!
在使用 CSS Grid 和自动填充列时,我该如何处理 sizes 属性? 是否可以知道列数何时会发生变化,从而影响图片大小?
感谢这篇文章。 讨论问题:在这种情况下,您拥有能够调整任何大小的后端。 让 LazyLoader 设置图片大小 URL 的参数是否更有意义? 我看到了优缺点
更具动态性
适用于整个网站和所有图片
更多控制权
发送的 HTML 更少(但 JavaScript 更多。 这取决于……)
+/- 浏览器支持
浏览器控制权更少(连接等)
调整大小时没有浏览器缓存(好的,更多 JavaScript 并且问题消失了)
JavaScript 依赖性(好的,有帮助)
LazyLoader 与
srcset
/sizes
之间的争论现状如何?假设您有后端缓存调整大小的图片,则调整到任何大小意味着您将拥有巨大的缓存存储空间。
此外,“按需”调整大小意味着更多人将获得给定大小的首次命中,延迟更高(尚未缓存)。
此外,延迟加载意味着您需要等待 JS 加载并执行,因此浏览器必须等待,而使用
sizes
,它甚至可以在加载任何 CSS 和/或 JS 之前下载正确的图片。 IMHO,不应在页面顶部使用。假设您有
<
div id=content width=75%>
现在,100 vw 的图片是否会填充
整个屏幕
屏幕的 75%——content ID 宽度
现在,假设您将图片的样式设置为 50% 宽度。
会发生什么?
假设您将图片放在一个容器中
图片
图片标题
并且此 div 的样式设置为其父容器(content)宽度的 30%,图片将缩放为该宽度的 90%。
鉴于其他事物的运作方式,我预计图片的大小将与其容器相关。 浏览器是否足够智能,可以在做出决定之前查看图片的空间?
sizes
如果尽快计算,以便浏览器可以尽快下载最佳图片。它发生在加载和计算任何 CSS 之前。
因此,如果您使用
sizes="100vw"
,使用 CSS 将图片显示为小于视口宽度,这意味着您正在下载比所需更大的图片。 这就是为什么您需要同步 CSS 布局和sizes
的原因。