之所以会翻译这篇文章是因为我昨天看到@勾三股四的这篇微博,里面推荐的文章就是下面我要翻译的。因为自己一直对响应式图片这个技术很关注,但是一直没有一个很好的总结机会,今天趁着翻译这篇文章总结了,这是本人翻译的第一篇文章,有错误的地方请指出。
博客地址 欢迎关注
剖析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
原文中
<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>
。
扩展阅读
希望上面的文章能够对各种用例起到参考作用,你可以继续看看下面的文章:
十段响应式图片文章 - Jason Grigsby
响应式图片:用例和代码片段 - 和这篇文章类似,但是有更多用例
Client hints - 服务端代替响应式图片的方法
译者推荐文章
与本文结构类似的文章:
补充文章:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。