之所以会翻译这篇文章是因为我昨天看到@勾三股四的这篇微博,里面推荐的文章就是下面我要翻译的。因为自己一直对响应式图片这个技术很关注,但是一直没有一个很好的总结机会,今天趁着翻译这篇文章总结了,这是本人翻译的第一篇文章,有错误的地方请指出。
原文地址
剖析responsive image
最近对 responsive image 有一些感悟然后赶紧记下来免得忘了。下面就是我的感悟:
如果你是用像素来固定图片尺寸,又想在不同屏幕密度屏幕上实现响应式图片,可以这样:
<img width="320" height="213" src="cat.jpg" srcset="cat-2x.jpg 2x,cat-3x.jpg 3x">
它可以正常运行在 所有现代浏览器 上,而且在不支持 srcset 的浏览器也可以降级到 src 。
有一些规则是上面图片所没有提到的:
srcset 里的每一项都是 <url> <density>x 结构 ,就像 cat-2x.jpg 2x srcset 里项目的顺序并不重要 width / height ,浏览器会按照屏幕密度展示它本身原始的 width / height 。 比如 2x 资源被匹配到了,它会被渲染成本身的 50% width 和 50% height 3x 设备像素比的设备上浏览器渲染的是 1x 的图片,可能是因为糟糕的网络环境 案例
这个案例使用的是3张一样的图片,只是尺寸不一样,这样我们很难看出区别。所以译者在这里换了这几张图,然后在Chrome中模拟手机调试,更换分辨率,应该就很明显了。
译者案例
这种方法因为要人为匹配设备像素比,所以 1x 、 2x 、 3x 、 4x 等等,这样HTML就会太臃肿,所以有了下面的新方法。
不同宽度的图片在响应式站点里是很常见的。在这篇博客里,图片内容都是占据了文章100%的宽度,但是文章的宽度并不总是窗口宽度的100%。
为了让浏览器匹配到正确的图片,我们需要知道:
<img> 的宽度 最后一点是特别困难的,因为图片开始下载是在CSS解析之前的,所以 <img> 的宽度不能从页面布局那得到。
<img src="panda-689.jpg" srcset = "panda-689.jpg 689w, panda-1378.jpg 1378w panda-500.jpg 500w panda-1000.jpg 1000w" sizes = " (min-width:1066px) 689px, (min-width:800px) calc(75vw-137px) , (min-width:530px) calc(100vw-96px) , 100vw" >
通过 srcset 属性,浏览器知道了哪些图片可用以及这些图片的宽度。
通过 sizes 属性,浏览器知道了 <img> 相对于一个已知宽度窗口的宽度。
这样,浏览器就可以匹配最佳资源加载了。
你不再需要说明屏幕密度,浏览器自己会辨别。如果浏览器窗口宽度是 1066px 甚至更大, <img> 会被定为 689px 。在 1x 设备浏览器上会下载 panda-689.jpg ,但是在 2x 设备浏览器上将会下载 panda-1378.jpg 。
这里感觉作者并没有解释清楚 sizes 和 srcset 的工作原理(参照下面的 译者案例 来看)。
首先,是关于 sizes 的理解:
比如当前窗口 800px ,那么 sizes 会匹配到 (min-width:800px) calc(75vw - 137px) ,则这个 <img> 对应的宽度就是 800px*0.75-137px=463px 。这个宽度的设定相当于
<img src="..." width="463" /> 知道了 <img> 的 width ,然后再看 srcset 的 w :
在 dpr 为 1 的时候, 463px 对应 463w ,查找 srcset ,找到 500w 适合它,就显示500的这张图。
在 dpr 为 2 的时候, 463px 对应 926w ,查找 srcset ,找到 1000w 适合,就显示1000的这张图。
一些规则是上面没有提到的:
srcset 里的每一项是 <url> <width-descriptor>w ,比如 panda-689.jpg 689w srcset 里每一项的顺序没有影响 srcset 包含了一个宽度描述符( w ),则 src 会被那些支持 srcset 的浏览器忽略掉 sizes 里的每一项是 <媒体查询> <图片宽度> 形式,除了最后一个仅仅是 <图片宽度> sizes 里的宽度单位都是 px sizes 里的第一个匹配到的媒体查询,所以 sizes 里的顺序是很重要的 如果你没有指明 <img> 的宽度,浏览器也会正常解析。对 sizes 精确设置,但是一个不是很确切的宽度也很好。比如
sizes="(min-width:1066px) 689px , (min-width:800px) 75vw,100vw" 挑选哪些图片资源放在 srcset 里是很困难的,我也没有完全掌握技巧。在上面的例子里,我设置了一个最小尺寸(注:原文中是最大)( 689px ),然后给 2x 设备设置刚才的两倍尺寸( 1378px )。另外两个设置是在这两个值中间任意取的。我没有设置更小的宽度比如 320px ,因为在这一情况下的屏幕密度是 2x 或者更高。
srcset + sizes 在 Chrome、Firefox和Opera中都兼容。至于其他浏览器,也会很安全地回退到 src 属性。不用等待很久, WebKit nightly 和 下一个稳定版本的 Edge 就会很好地支持它。
WebKit nightly 是WebKit的 mac port ,对于 Safari 就像 Chromium 对于 Chrome
开发者需要了解的WebKit
案例
原文中 <img> 有一个内联样式 width:100% ,一开始没有注意到的话还以为没有变化呢。上面的案例已经修改过了 -。-
还是因为作者使用了内容相同,尺寸的图片,所以我换了图片重新做了一个例子:
译者案例
这种新方法的 srcset 用来指向提供的图片资源,没有上面方法的 1x 、 2x ,这个都交给浏览器。例子中就指向了3个尺寸图片。
sizes 用来表示尺寸临界点,用媒体查询定下图片的实际宽度。
和之前的例子类似除了框架的不同宽度的变化。它允许你集中精力对付更小的宽度。
<source> <img> <source> 元素上总是被服从的 <img> 的 <source> 会被使用,所以顺序很重要 <source> ,则 <img> 被调用 <img> 必须出现在 <source> 后面 <source> 不支持 src ,但是支持 srcset 一旦 <source> 或者 <img> 被选中, srcset 和 sizes 属性就像之前的例子一样解析。
艺术指导 :剪裁图片内容来适应特定环境,任何时候我们裁剪或是修改图片来适应一个断点(而非简单缩放),都是一种艺术指导。
可以看出来,艺术指导比之前的 srcset + sizes 又多了一层维度: source 的媒体查询。
<picture> 元素在Chrome、Firefox和Opera中 兼容良好 ,在其他浏览器可以回退到 <img> 。而下一代的 Edge也可能会支持 。
案例
这个方法可以让你有更优化的方式去提供给支持它们的浏览器。
<picture> <source type="image/webp" srcset="snow.webp"> <img src="snow.jpg"> </picture>
type 属性是 mime 类型 type 和 media 、 srcset 甚至是 sizes 取创建一些惊奇的东西 它在Chrome、Firefox和Opera上 兼容良好 ,其他浏览器还可以回退到 <img> 。
案例
希望上面的文章能够对各种用例起到参考作用,你可以继续看看下面的文章:
与本文结构类似的文章:
Google Developers dev.opera 结构十分清晰