HTML5提出的<picture>
标签非常实用,在新时期用户体验大方向上可以结合css以及其它HTML元素达到意想不到的效果。
picture往往和<source>
元素(可以多个)、<img>
元素(最多一个)一同使用。
- source
1. srcset:接受固定的图片文件路径(比如
)或是用逗号分隔的用像素密度描述的图片路径(比如
)
2. sizes:接受固定的宽度描述(比如sizes="100vw"
)或media query宽度描述(比如sizes=(max-width: 30em) 100vw"
),如果有逗号,最后一个被当做是默认值
3. media:接受任何验证的media query。像css的@media选择器那样 - img
渲染的时候,浏览器优先使用<source>
元素,<img>
元素兜底。
结合近两年W3C年度报告来看,前端(尤其是css)开始往用户体验方向突破。一方面目前已经很难有大方向的创新,另一方面有Google这个“急先锋”存在,已经势不可挡了。
你可能已经知道,img标签提供了 srcset 用来提供同一图片的不同大小的版本:
<img src="" srcset="" sizes="" alt="">
你可以这么用:
<!-- 根据设备DPR提供不同尺寸的图片 -->
<img
src="srcset-x1.png"
srcset="
srcset-x1.png 1x,
srcset-x2.png 2x,
srcset-x3.png 3x"
alt="srcset for img"
/>
<!-- 根据视窗大小提供不同尺寸的图片 -->
<img
alt="A baby smiling with a yellow headband."
src="/baby-640w.jpg"
srcset="
/baby-320w.jpg 320w,
/baby-640w.jpg 640w,
/baby-960w.jpg 960w,
/baby-1280w.jpg 1280w,
/baby-1920w.jpg 1920w,
/baby-2560w.jpg 2560w"
sizes="
(max-width: 500px) calc(100vw - 2rem),
(max-width: 700px) calc(100vw - 6rem),
calc(100vw - 9rem - 200px) "
/>
其中,sizes
就是尺寸的意思,图片属性先判断目前要用那个宽度来找srcset
,然后此时的图片会按照sizes的对应值展示大小!
不管是根据设备DPR还是视窗大小选择不同尺寸的图片,图片到底是同一张,只是尺寸大小不同,最终呈现给用户的效果只是图片的缩放。
而 picture 标签不一样,如果你不单单想更改图片尺寸,还想在不同场景下展示不同图片,那你大可以使用它。
上面说的不同场景都有啥呢?举几个🌰:
比如不同分辨率
<picture>
<source media="(max-width: 799px)" srcset="https:///sites/default/files/blogs/2021/2112/elva-480w-close-portrait.jpeg">
<source media="(min-width: 800px)" srcset="https:///sites/default/files/blogs/2021/2112/elva-800w.jpeg">
<img src="https:///sites/default/files/blogs/2021/2112/elva-800w.jpeg" alt="Chris standing up holding his daughter Elva">
</picture>
呈现给用户的图片会有两个阶段:
- 在大屏幕上,显示一张大的图片
- 在小屏幕上,显示一张小的图片(基于大图片裁剪过的一张新图片)
浏览器会根据CSS媒体查询设置的断点切换图片。它和<img>
最大不同之处就是可以在不同的视窗大小或像素比定义不同图片资源!其明显的好处是,适当尺寸的图片资源被提供,这最终可以节省大量的带宽,而且图片呈现效果比直接缩放效果要更佳。
你也可以像上面img那样使用x
单位:
<source
srcset="
square-large.jpg 2x,
square-small.jpg 1x"
/>
表示引入的图片源将根据用户设备的 DPR来做图片源的选择,在dpr=2
的时候会选择square-large.jpg,在dpr=1
的时候会选择square-small.jpg。
比如暗黑模式
目前为止像这样裁剪和缩放图片是最常见的艺术指导形式,但它起的作用绝不仅此而以,它还可以帮助你做更多的事情。
暗黑模式在web中很火,为了能给用户一个更好的体验,希望让Web上的图片在Light和Dark两种模式下略有不同。大多数,开发者喜欢使用 CSS 滤镜 和 媒体查询来处理图片:
@media (prefers-color-scheme: dark) {
img:not([src*=".svg"]) {
filter: brightness(.8) contrast(1.2);
}
}
或者:
body{
filter: invert(1) hue-rotate(180deg);
}
invert(xxx);
—— CSS中的“反相”:其作用元素拥有这个值时会发生色调“翻转”,比如:白-黑;当作用元素是img图片时,会使图片色调也反转。而hue-rotate(deg)
针对图像应用色相旋转。"angle"一值设定图像会被调整的色环角度值。值为0deg,则图像无变化。若值未设置,默认值是0deg。该值虽然没有最大值,超过360deg的值相当于又绕一圈。
不过,使用<picture>
效果会更佳:
<picture>
<source srcset="https:///sites/default/files/blogs/2021/2112/dark.png" media="(prefers-color-scheme: dark)">
<source srcset="https:///sites/default/files/blogs/2021/2112/light.png" media="(prefers-color-scheme: light)">
<img src="https:///sites/default/files/blogs/2021/2112/light.png" alt="" />
</picture>
在 media属性中prefers-color-scheme
的条件值为 dark 时引入 dark.png 图片,在prefers-color-scheme
为 light 时引入 light.png 图片,并且在不支持 prefers-color-scheme
的设备上使用 light.png 图片。
比如一些不那么关键的动画效果
虽然但是,并不是所有人都会喜欢“动画”:
- 有些用户面对闪烁的动画可能会诱发癫痫病发作
- 有些用户会因为动效产生类似晕车的反应
系统推出了prefers-reduced-motion: reduce
来减弱或禁用动效。用户可以手动更改值。
在用户体验方面,我们确实要考虑到不同的情况。在我司最近的项目中,笔者已经引入了此特性。 —— 《分享:尽量减少不必要动画和非关键弹窗对用户的“打扰”》
虽然说现在Web上的动效大多可以使用 CSS 或 JavaScript 来完成,但有的时候还是会使用 .apng
或 .gif
格式的动图。如果希望在用户开启了禁用动效的设置,不展示动图而使用一张静态图:
<picture>
<source
srcset="https:///sites/default/files/blogs/2021/2112/animation.jpg"
media="(prefers-reduced-motion: reduce)"
> </source>
<img srcset="https:///sites/default/files/blogs/2021/2112/animation.gif" alt="" />
</picture>
或者:
<picture>
<source
srcset="https:///sites/default/files/blogs/2021/2112/animation.gif"
media="(prefers-reduced-motion: no-preference)"
> </source>
<img srcset="https:///sites/default/files/blogs/2021/2112/animation.jpg" alt="" />
</picture>
再说说picture的source
<picture>
最大的特色是同时包含 <source>
和 <img>
。其中<source>
元素允许开发者为<img>
元素指定多个备选源集。它本身并不代表任何东西。比如:
<picture>
<source srcset="small-200.jpg 200w" sizes="(max-width: 639px) 100vw">
<source srcset="medium-650.jpg 650w" sizes="(min-width: 640px) and (max-width: 1023px) 50vw">
<source srcset="large-850.jpg 850w" sizes="(min-width: 1024px) 25vw">
<img src="my-image.jpg" alt="My image">
</picture>
在 <picture>
中同时可以出现多个 <source>
元素来指定图片源,并且会从第一个开始索引。如果第二个符合条件,将会采用第一个引入的图片源;如果第一个不符合条件,会根据第二个<source>
,依此类推,直到找到符合条件的图片源。如果所有<source>
的图片源都不符合,则会采用<img>
备用,最终呈现给用户的是<img>
的src
引入的图片源。
不过,我们使用<picture>
时,用户实际上看到的是<img>
元素。如果picture中没有img,用户就看不到图像,因为picture和其所有的source子元素只是为了给img提供一个来源。它的来源(<source>
)只是让浏览器知道从哪里提取图片的来源,用来替代<img>
中的src
引入的图片源。这也意味着,任何想应用于渲染图片的样式(比如,max-width: 100%
)都需要应用于img元素上:
/* 不会被应用到图片上 */
picture {
max-width: 100%;
height: auto;
}
/* 会应用到图片上 */
img {
max-width: 100%;
height: auto;
}