原文链接点击打开链接
固定的大小,可变的密度
如果你的图片大小是固定且以像素为单位的,但同时你又想把它投影到不同分辨率的屏幕上的话
这一招对所有现代浏览器都管用,而对于老式浏览器则只会解析到src为止
下面是一些没有在上图转换时用到的规则:
l 每个在srcset里的项目语法都是<url> <density>x, 比如cat-2x.jpg 2x
l Srcset里的项目顺序无关紧要
l 如果你没有声明宽/高,那么浏览器会显示图片本身的宽高除以其密度。比如如果挑选了2x比例的资源,它将会被渲染成原宽高的一半
l 这仅仅是一个提示,甚至在3x的设备上,浏览器也可以使用1x的图片。可能是因为低连通性造成的
一个生动的例子
<figure class="full-figure">
<img alt="A cat" width="320" height="213" src="/static/posts/responsive-images/cat-1x.b3b4dfd8b1a9.jpg" srcset="/static/posts/responsive-images/cat-2x.bf14e0862bb8.jpg 2x, /static/posts/responsive-images/cat-3x.jpg 3x"
</figure>
.full-figure img, .full-figure iframe, .full-figure video, .full-figure object {
display: block;
margin: 0px auto;
}
img {
max-width: 100%;
}
可变大小和密度
可变宽度的图片常用在响应式页面上。在这篇博客,图像内容占用文章100%的宽度,但是文章并不总等于窗口宽度。
浏览器为了能选择正确的图片,则需要知道:
l 该图像各种尺寸对应的URL
l 每个图像解码后的宽度
l <img>标签的宽度
最后一点是最复杂的。因为当下载图像发生在css文件准备加载完成之前时,浏览器没办法从页面布局中解析<img>的宽度。
理解这个语法的关键在于知道哪些值对应窗口的宽度、解码后的宽度和<img>宽度。
通过srcset,浏览器能知道某个资源是否可用及其宽度。通过sizes浏览器得到了在特定窗口大小下 <img> 元素的宽度。这样浏览器就能选出并加载最合适的资源。
你不用知道具体的密度,浏览器会帮你计算它。当窗口宽度大于等于1066px时,我们已经设置了<img> 的宽度为689px。在1x设备上,浏览器则会加载panda-689.jpg,但是在2x设备上浏览器则会下载panda-1378.jpg。
下面是一些没有在上图转换时用到的规则:
每个在srcset里的项目都由<url><width-descriptor>w组成,比如panda-689.jpg 689w
srcset内部的顺序无关紧要
如果srcset包含了一个宽度描述符,则支持的srcset 浏览器会忽视src标签
在sizes内的每个项目的形式必须是<media-condition><image-element-width>,除非最后一项只有<image-element-width>。(Each item within sizes is <media-condition> <image-element-width>, except for the lastentry which is just <image-element-width>)
sizes里的两个宽度都是以CSS像素定义的
浏览器只使用第一个匹配的媒体条件,所以顺序是很重要的。
正如上面所说,浏览器可能会因为其他因素而下载较低像素的图片,比如低连通性时。
选择要列出的sizes 属性是一个很直接的过程。从你窗口最低宽度开始,随着其大小的增加,根据窗口大小的改变来创建相应的 <img>尺寸新规则。
当窗口缩到最小时, <img>占据全部宽度,或者是100vw。当窗口超过530px时,该页内容区域则得到32px左内边距和64px的右内边距,这样<img>就变为calc(100vw - 96px)。
浏览器在你谎报 <img>的宽度时并不会报错。我一直在项目里精确地设置sizes属性,但是一个粗略的答案是不够好的,比如sizes="(min-width:1066px) 689px, (min-width: 800px) 75vw, 100vw"。(The browser won't call the police if it finds out you liedabout the <img> width. I've beenaccurate with my sizes, but a rough answer canbe good enough, eg sizes="(min-width: 1066px) 689px, (min-width: 800px) 75vw,100vw".)
挑选并创建合适的资源更为困难,并且我不认为我掌握了这门技巧。在上面的例子里我设置了图片最大尺寸为689px,在2x设备上翻倍成1378px。另外两个是大致的中间值。我并没有涵盖近更小的屏幕尺寸,比如320px,按照假设该尺寸屏幕下密度将会是2x或是更高。
srcset + sizes在Chrome,火狐和Opera上奏效。对于其他浏览器,它将会安全地使用src。你为浏览器支持等待太长,它会在稍晚事件出现在Webkit上以及下一代Edge。
一个生动的例子
<figure class="full-figure">
<img style="width:100%" alt="A red panda eating leaves" src="/static/posts/responsive-images/panda-689.6adaf8a7c694.jpg" srcset="/static/posts/responsive-images/panda-689.6adaf8a7c694.jpg 689w,/static/posts/responsive-images/panda-1378.jpg 1378w, /static/posts/responsive-images/panda-500.jpg 500w,/static/posts/responsive-images/panda-1000.jpg 1000w" sizes="(min-width: 1066px) 689px,(min-width: 800px) calc(75vw - 137px),(min-width: 530px) calc(100vw - 96px),100vw">
</figure>
.full-figure {
margin: 1em -20px;
overflow: hidden;
background: #eee;
@media screen and (min-width: $mobile-boundry) {
margin-left: 0;
margin-right: 0;
}
&.checked {
background: url('imgs/check.png');
}
& img,
& iframe,
& video,
& object {
display: block;
margin: 0 auto;
}
& .video {
position: relative;
padding-top: 56.25%;
& iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
& > figcaption {
font-size: 0.8rem;
background: #FFE454;
color: #000;
padding: 0 20px;
@media screen and (min-width: $mobile-boundry) {
padding: 0 10px;
}
}
}.full-figure img, .full-figure iframe, .full-figure video, .full-figure object {
display: block;
margin: 0px auto;
}
img {
max-width: 100%;
}
![A red panda eating leaves](https://jakearchibald.com/static/posts/responsive-images/panda-689.6adaf8a7c694.jpg)
可变宽度,密度以及art direction
和前面的例子类似,但是取景则根据宽度发生改变。这让你能在不同的宽度下对焦物体。(Similarto the previous example, but the framing changes at different widths. Thisallows you to focus in on the subject at smaller widths.)
你可以根据你的需要设置多个<source>
你必须设置<img>
始终遵守<source>上的媒体查询,这不仅仅是提示
媒体查询是基于窗口宽度的,而非<img>
浏览器使用第一个匹配的<source>,所以顺序很重要
如果没有匹配的<source>,则使用<img>
<img>必须出现在<source>之后
<source>并不支持src,但是srcset="whatever.jpg"也能正常工作
一旦选择了<source>或<img>,srcset和sizes属性会像前面的例子一样正常运作,因此你可以举一反三。
<picture>元素在Chrome,火狐和Opera上奏效。对于其他浏览器,它将会安全地使用<img>。
一个生动的例子
<figure class="full-figure">
<picture>
<source media="(max-width: 800px)" srcset="/static/posts/responsive-images/f1-focused-800.867f0b0b832f.jpg 800w,/static/posts/responsive-images/f1-focused-1406.jpg 1406w" sizes="(min-width: 530px) calc(100vw - 96px), 100vw">
<img style="width:100%" alt="F1 car in the gravel" src="/static/posts/responsive-images/f1-689.d6ed1b428a74.jpg" srcset="/static/posts/responsive-images/f1-689.d6ed1b428a74.jpg 689w,/static/posts/responsive-images/f1-1378.jpg 1378w, /static/posts/responsive-images/f1-500.jpg 500w, /static/posts/responsive-images/f1-1000.jpg 1000w" sizes="(min-width: 1066px) 689px, calc(75vw - 137px)">
</picture>
</figure>
变化类型
这个方法允许你为浏览器提供更合适的格式。
type 是mime类型
你可以为media,srcset设置多个资源和混合类型,甚至是设置sizes来创建了不起的视觉效果
这在Chrome,火狐和Opera上奏效。对于其他浏览器,它将会安全地使用<img>。
一个生动的例子
<figure class="full-figure">
<picture>
<source type="image/webp" srcset="/static/posts/responsive-images/snow.c9eadd40e48a.webp">
<img style="width:100%" alt="Hut in the snow" src="/static/posts/responsive-images/snow.9f5756525434.jpg">
</picture>
</figure>