如果您正在实施响应式图片(为不同情况在 HTML 中使用不同的图片),并且您只是在不同版本的同一图片之间切换(绝大多数使用情况),那么您只需要在 <img>
上使用 srcset
属性。 看看这个简单的语法
<img src="small.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" alt="yah">
不仅仅是语法很简单,它比使用显式 media
属性的 <picture>
和 <source>
做得更好(我们稍后会解释原因)。 此外,它还有机会在未来随着浏览器设置和浏览器改进而变得更好。
我之前已经录制过关于这个主题的视频了,但看完 Mat Marquis 在 An Event Apart Austin 的演讲以及 Jason Grigsby 的文章 后,我对此有了更深的理解。 我在这里再次写它,因为我认为我们所有人都应该理解它。
srcset
,浏览器会负责找出哪张图片最合适
使用 在上面的简单示例中,我们所做的只是告诉浏览器我们有哪些图片可用以及它们的大小。 然后浏览器会独立完成所有工作,找出哪个图片最合适。
Mat Marquis 通过展示浏览器如何用数学方法来解决这个问题进行了演示。 假设您使用的是屏幕宽度为 320px 的设备,并且它是一个 1x(非视网膜)显示屏。 并且您拥有的图片是 small.jpg(500px 宽)、medium.jpg(1000px 宽)和 large.jpg(2000px 宽)。
浏览器会执行以下操作
让我做一些没人关心的快速计算,除了我自己。
500 / 320 = 1.5625
1000 / 320 = 3.125
2000 / 320 = 6.25
好的,因为我是一个 1x 显示屏,1.5625 是最接近我需要的。 它有点高,但与其他高得多的图片相比,它是最佳选择。
现在另一个浏览器访问了该网站。 它也是一个 320px 显示屏,但它是一个视网膜(2x)显示屏。 该浏览器会执行相同的计算,然后会执行以下操作
好的,因为我是一个 2x 显示屏,我会舍弃 1.5625 图片,因为它对我来说太低了,可能会看起来不好。 我会使用 3.125 图片。
您是否看到了它的实用性? 您让浏览器自己找出最合适的图片,而不是您自己费力地去想。
浏览器将变得更加智能
请记住,使用 srcset
这种方法已经带来了益处,但它将变得更好。 将 srcset 视为建议或帮助浏览器做出决定的额外信息。 最终,它可以做它认为正确的事情。 这意味着
- 浏览器可以提供有关图片的用户偏好
- 浏览器可以开始考虑带宽
是的,这是理论上的,但很可能实现。
如果您使用带有显式来源的 <picture>
,浏览器必须严格按照您的指示操作,不能自己做出选择。 现在,<picture>
可以被设置为执行 srcset
目前正在做的事情,只是它更冗长,而且没有改进的空间。
sizes
另外,我们故意没有在这里讨论 sizes 属性。 实际上,将其省略也还不错。 在这种情况下,它会假设 sizes="100vw"
,这意味着
我假设您在使用图片时,它会占据整个视窗的宽度。
这通常不是一个糟糕的假设。
如果您愿意,您可以对它进行各种特定的配置。 您可以使用 sizes 属性来精确匹配您的 CSS 布局,并告诉浏览器该图片在每个屏幕尺寸上将有多大,与您的设计中的断点匹配。 这可能会有点复杂,老实说,它可能有点危险,因为您将 CSS 内容放在标记中,您知道这会带来什么后果。 Eric Portis 刚写了一篇关于这个问题的文章。 理想情况下,它可以被自动化或在服务器端注入。
我认为某种“通用”的 sizes 属性可能会有用。 在一个类似博客的通用网站上,也许在内容中使用以下代码是一种明智的做法
sizes="(min-width: 800px) 50vw, 100vw"
含义:“如果浏览器窗口宽度大于 800px,该图片可能会显示为其宽度的一半。 如果更小,它可能会占据整个宽度。”
为什么讨论这个问题?
再次强调:绝大多数响应式图片的使用情况并非基于“艺术指导”。 艺术指导是一种高级用例,请随意使用它。 <picture>
在这方面非常出色。
大多数响应式图片的使用情况将是:“我有这个图形的多个版本。 它们就在这里,请使用正确的版本。”
这是一个非常令人困惑的话题。 它需要被思考和撰写,以便它能够脱颖而出,成为我们前端开发人员集体意识中更根深蒂固的一部分。
Tim Evko 创建了一个 用于响应式图片的 WordPress 插件。 它利用 WordPress 的能力来创建图片的较小版本。 然后您点击您想要的图片,它最终会输出创建该图片所需的响应式图片代码。 目前,它使用 <picture>
。 这是因为 <picture>
在前端开发人员集体意识中比 srcset 更深入人心。 Tim 正在 试图理解这一切,以便他能够弄清楚是否以及如何更改该插件。
@Tevko @brad_frost srcset/sizes = 帮助浏览器决定哪张图片最合适的信息。 Picture 带有 media 属性 = 明确的 DO THIS ONLY
— Chris Coyier (@chriscoyier) 2014年9月29日
何时使用?
这也很棘手。
如果您现在需要它,并且需要良好的 浏览器支持,您需要使用 polyfill。 但这 可能会带来一些潜在的弊端。 因此,目前您需要自己做出决定,我不确定是否以及是否存在适用于所有场景的最佳实践。
很棒的内容。 非常有用,谢谢。
我相信插件需要更改,并且很快就会修复! 唯一剩下要决定的是要创建多少个默认图片尺寸,以及是否要省略 sizes 属性,或者包含一个典型的博客默认值。 大家都欢迎在 Github 上加入讨论!
还有一点要提一下(据我所知,尽管我不能说自己是专家)
如果您的浏览器大小发生变化——例如,因为桌面用户调整了窗口大小或移动用户从横向模式切换到纵向模式——
<picture>
语法会强制浏览器切换图片,下载一个新文件。 如果新文件只是浏览器正在使用的文件的缩小版本,这对于带宽和整体网页性能来说非常不利。 使用 srcset,浏览器可以看到旧文件仍然可以使用,并像往常一样缩放它。我认为关键在于,当您更担心图片对用户的显示效果时,使用
picture
;而当您只需要呈现一些质量/可读性不是问题的东西时,使用srcset
。是的——这在目前的(计划)实现中没有,但 Firefox 已经在考虑它。
规范的这部分故意留有模糊之处,以便浏览器有空间进行像这样的优化。 未来还有很大的改进空间。
越来越像浏览器推动发展而不是 W3C。这在 Chrome 34 中,如果 FF 支持它,它也在 IE12 中,那么它就等同于被接受了。但是如果 W3C 改变了标准和/或合并了 picture 和 image 标签,会发生什么呢?
W3C 主要由主要的浏览器供应商组成。
是的。不仅如此,w3c 故意不会将任何东西放到标准轨道上,除非浏览器有兴趣实现它(或者更常见的是,已经实现了它)。规范并不总是与实现相匹配——想象一下,如果与供应商没有协调和支持,情况会变得多么糟糕。
有人知道为什么使用 “” 无法让浏览器做出决定吗?我很乐意使用它,非常感谢你发布这篇文章,Chris,我只是想知道为什么。
使用什么?在我这显示为 “”。
<picture> 用于当你真的需要在不同尺寸下切换不同的图片(不仅仅是不同的分辨率)的时候。
例子
如果你有一个你想让它填充整个窗口的横幅图片,你可能需要在纵向和横向模式下使用不同的裁剪版本。目前,如果你想替换不同的图片文件,你必须使用 CSS 背景图片而不是标记图片。
如果你有一个带文字的图表,你可能需要一个更紧凑的版本,在更大的字体大小下显示更少的文字,相对于图片的其余部分。(你可以在单个 SVG 图片文件中获得这种效果,但这很麻烦,需要大量自定义 CSS 来隐藏或显示文本。)
在这些情况下,如果浏览器插入了错误的文件,布局/设计可能会变得不可用,或者至少很丑陋。
不幸的是,根据 caniuse.com,
srcset
和picture
并不被目前可用的浏览器广泛支持。希望他们至少在今年年底开始实现它。
@Victor: 即使在不支持它的浏览器中,使用带有 srcset 属性的 img 也是安全的,因为你仍然使用了 src 属性。支持 srcset 的浏览器将使用新功能,不支持的浏览器将回退到 src 属性。
你也可以使用 PictureFill polyfill 为旧浏览器添加对 picture 元素和 srcset 的支持。
似乎主要的移动浏览器都支持它,所以使用 src 作为你的桌面图片,使用 srcset 作为较小的断点图片就可以工作了。
不过这依赖于移动浏览器不会同时下载 src 和相关 srcset 图片。有人知道它们是否足够智能以避免这种情况吗?
不用担心:使用
src
和srcset
不会进行双重下载——同样,在支持picture
的浏览器中,img
也是回退机制。当你使用 polyfill 时,这方面可能会变得很棘手,但如果你依赖于原生的回退模式,则不会有浪费下载的风险。我一直使用 picturefill 根据我网站的断点替换不同大小的相同图片。所以如果屏幕很小,它就会获得最小的图片(尺寸和文件大小)。使用 srcset,如果小屏幕是视网膜屏,它就不会再获得最小的图片了。如果出于性能原因,我想要这样,我应该坚持使用 picture,对吧?
所以如果我理解正确,在我们的 CMS 中,支持视网膜图片非常简单,这些图片目前以实际尺寸显示。我们会首先添加一个 srcset,其中包含正常图片(也在 src 属性中)和 2x 图片(以像素为单位指定大小),然后设置 sizes=“原始图片的宽度(以像素为单位)”。我猜只有当你需要对图片显示的大小进行更精细控制时才会变得棘手。
sizes 的 100vw 假设很有趣,但我想这个过程必须在没有 CSS 的情况下运行,因此它不能假设容器宽度的 100% 或类似的值。
Chris 的文章很棒……你的博客让我保持更新,从没让我后悔做网页设计。
为什么在 srcset 中使用 500w 和 1000w 比将较小的图片放在 src 中,将较大的图片放在 srcset 中并使用 2x 更好?
如何使用响应式图片作为背景图片?
媒体查询!
非常有见地,谢谢!
所以基本上
img
标签上的srcset
已经可以用了,因为它没有缺点,即使浏览器不支持它。不会有双重下载。只有改进。我发现两句话可能需要修改
嗨 Chris,我一直在很多网站上看到这些链接的文章,终于等到了… 有用的文章,一如既往。
一点无耻的自我推广
你可以看看我的 WordPress 插件 Responsify WP,它支持
picture
和span
作为标记模式。它还可以处理背景图片。一个支持 srcset/sizes 的新版本将在几天内发布 :)
但我必须说,我发现很难理解 srcset/sizes 属性是如何协同工作的。
如果你使用 w 描述符。我建议你也将 src 回退图片描述放在 srcset 属性中
我目前在我的一个开发网站上使用它,它非常适合图片清晰度,但我认为它需要解决带宽问题。我保存了 1x 图片(优化到 60%)、2x 图片(优化到 20%),并在所有可能的地方使用 svg,这很有帮助,但当有人在手机上使用 2x 屏幕时加载最大的图片(所以它基本上很漂亮)就有点奇怪,因为不久前我们想要加载更小的图片,这样网站和图片就能更快地加载……现在我们正在加载更大的图片。
我们花费了大量时间减少 http 请求、雪碧图,然后是图标字体,现在是 svg,为了速度、速度、速度……所以现在让我们仅仅根据像素密度加载最大的图片。帮我理解一下?
谢谢!
嗯,SVG 不仅仅是为了速度,但希望要点没有遗漏。
这就是为什么响应式图片的下一个发展方向是浏览器选项,让用户决定是否想要高分辨率图片或低带宽文件。对于移动浏览器,理想情况下,这将允许用户根据使用移动网络还是 wifi 拥有不同的设置——或者甚至更具体,将漫游费和低速共享 wifi 考虑在内。
一旦浏览器拥有关于用户偏好的这些数据,它就会将这些数据纳入决定从源集列表中下载哪个文件的过程中。但正如 Chris(另一个 Chris)在文章中描述的那样,这些浏览器优化选择只适用于
srcset
属性中的多个值,不适用于<picture>
中的多个<source>
元素。Opera 已经有一个浏览器模式可以减少下载大小,你可以实际设置浏览器,让它下载在 Opera 的代理服务器上压缩的文件,从而获得更快的(如果分辨率更低)网站。我怀疑他们已经(或者很快就会)将
srcset
选项纳入考虑,以便为使用这种“Turbo”模式的人选择最轻的文件。嗯,这是一个很难实现的功能。然而,它非常有用。
Chris,
这是我第一次知道图像可以做到响应式。我会尝试实现它。
如果遇到任何问题,我会回复你。
谢谢Chris,好文章!不过这两个概念中,仍然困扰我的问题是每个元素都需要重复断点定义。使用anzeixer.js 有一个更好的、更优雅的解决方案,可惜它并不为人所知 - 所以请看一下并传播这个消息!;) 我写了一篇博客文章,介绍如何基于此实现一个简单的响应式图像解决方案:http://www.andre-abt.com/2013/09/16/responsive-breakpoints-and-images
关于如何使用srcset 的精彩文章。我认为许多开发人员实际上并没有使用浏览器内置的功能,它真的可以帮助你很多!
我认为一旦所有浏览器都支持它,我肯定会开始使用srcset,看起来现在使用width=”100%”或某种百分比是有意义的。感谢分享和未来的提示!
Teelah,你可以两者都使用。
例子
你有一个同一栋房子的三张不同尺寸的图片。超大尺寸(宽度为1600,高度为任意值),大尺寸(宽度为1200,高度为任意值),中等尺寸(等等)。你可以将图像容器设置为100%宽度,同时只加载相应的图像,这取决于显示区域和像素密度。
几个月前,我把一些旧代码片段的不同部分组合在一起,做了一些类似的事情。
你可以指定哪个视图模式使用哪张图片,此外,如果你附加了延迟加载,还可以使用一个默认的src作为旧的加载动画。
为了满足谷歌页面速度要求(img 图像尺寸的页面重绘),可以指定或动态计算图像的高度和宽度。
虽然不完美,但它满足了我对Bootstrap 3 响应式图像的需求。
https://github.com/ArranM/BootstrapImageReplacement
js 位于此处
https://github.com/ArranM/BootstrapImageReplacement/blob/Master/BootstrapImageReplace/Scripts/ImageReplace.js
我希望它能帮助到某个人。
感谢你分享这种很棒的响应式图像方法。它完美地工作了!
你们都在技术前沿;但用户没有。
非常有用的帖子,我会开始实施它。
在这篇文章之前,我一直考虑使用占位符图像(小于1kb),然后将一些图像设置为数据属性(小、中和大),并使用JavaScript根据屏幕宽度加载特定图像。但这是一个更好的解决方案。谢谢。
很棒的文章。解释得很棒。
使用srcset 和sizes 来强制在小型设备上进行艺术指导裁剪
在使用背景图片时,是否有替代方案?我发现它对背景图片更有用,因为它们是需要缩放的大图片。
@Jose: 只是在你的媒体查询中,在你的目标元素内部使用不同的“background-image”属性。
@Andre: 我熟悉这种技术,只是想知道是否有办法避免为每个断点显式指定唯一的背景图像。谢谢。
关于原始帖子中的HTML示例,我有一个问题:浏览器如何知道小图片的宽度为500px?
从我的角度来看,只在
src
中指定图片,而不在srcset
中指定图片,只有在1.5x/2x/3x语法中才有意义。在srcset
中指定图片宽度(200w、400w)时,应该在srcset
中指定备用图片。或者是我遗漏了什么?
好问题。我认为理想情况下,为了使这正常工作,需要在srcset 属性中复制small。
<img src="small.jpg" srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 2000w" alt="yah">
你能确认一下吗,Chris?
总的来说,这是一个为多个设备提供不同分辨率的响应式图像的好方法。
有人知道使用JavaScript/jQuery 操作使用srcset 方法生成的图像的解决方案吗?例如,这个非常简单的jQuery 图像切换代码 在Chrome/Opera 中会失效,因为它似乎完全忽略了“src”属性。
理想情况下,我甚至不希望获取“src”值,但我没有看到Chrome/Opera 在哪里指定它选择了哪张图片,以便能够获取该值并在其他地方使用它。
任何想法或建议都将不胜感激。谢谢!
不用了。看起来现在那个链接上可以工作了。
我一直在研究src-set,但似乎虽然我们谈论它很多,但实际上在没有polyfill的情况下,它几乎不可能或不切实际。
截至撰写本文时
* Firefox 需要启用开发人员标志
* 移动版 WebKit 仅支持 -x 语法,这对于从小型到大型的图像缩放(例如,英雄图像)几乎无用。截至 iOS 8.1,尚未支持 -w 语法。
* Android 的 AOSP 浏览器截至 4.4.4 尚未支持
* IE 尚未支持
* 令人费解的是,桌面版的 Chrome 38(以及现在的 Opera)具有最好的支持,而实际上我们特别需要它来支持移动设备。
谈论它很好,把它与picture(支持更少)进行比较也很好,但似乎甚至srcset 还没有准备好用于生产 - 实际上还要过一段时间。唉…
@Mike 我完全同意。
我刚在这个问题上卡了一段时间。当你使用
sizes
属性时,确保将最窄的图像尺寸放在首位。而不是最小的媒体查询。例如
(min-width: 62.5em) 25vw, (min-width: 30em) 50vw, 100vw
而不是(你可能期望的)
(min-width: 30em) 50vw, (min-width: 62.5em) 25vw, 100vw
我更喜欢像Bildero 这样的简单得多的解决方案,上传你的源图像(也就是说,你不需要创建small.jpg、medium.jpg 和large.jpg) - 只要上传原始图像,并简单地插入JS,你就可以拥有真正的响应式图像。
Bildero 会自动检测访问者的屏幕分辨率,并从你的原始图像中创建完美匹配的图像。我推荐它给每个人,因为它可以节省大量的时间和金钱(时间就是金钱,所以它可以节省金钱^2 :D)。