在此特地声明本文是根据 mozilla官方教学文档 学习的个人学习笔记,借用了大量的图片和文本内容,存在相当多的相同,但不是copy。如需查看mozilla官方文档,请点击前文链接!!
本模块要探索怎样用HTML来让你的网页包含多媒体,包括可以包含图像的不同方式,以及怎样嵌入视频,甚至是整个其他的网页。
html中的图片
深入使用<img>
元素,包括使用<figure>
添加说明文字,与CSS背景图片链接起来。
添加图片
<img>
是一个空元素,即不需要包含文本内容和闭合标签。最少使用一个src使<img>
生效。src属性指向要引用的图片的路径。
1 | <img src="images/example.jpg"> |
不推荐使用绝对路径,这会给浏览器造成更多的工作,在 HTML基础 中有提及。
在得到授权前不要把src属性指向其他人网站的图片,这侵犯了版权,这种行为被称为“盗链”。
备选文本
属性alt
,它的值是图片的文字描述,用于在图片无法显示或不能被看到的情况,即替代文本。
1 | <img src="images/example.jpg" alt="this is a picture"> |
备选文本的意义:
- 用户有视力障碍,通过屏幕阅读器浏览网页。
- 浏览器不支持该图片类型。例如Lynx,一个纯文本浏览器。
- 提供文字描述给搜索引擎使用。
- 用户关闭图片显示以减少数据的传输。
alt应该写些什么?这主要取决于图片在这里的目的。
- 装饰:只是用于装饰,不是内容的一部分,可以写一个空的,即
alt=""
。实际上装饰性的图片应该在CSS中设定。 - 内容:如果在图片中提供了重要信息,就应该在alt中简要提供相同的信息。注意不要写冗余的信息,
- 链接:如果把图片放在
<a>
标签里,把图片变成链接,还应该提供无障碍的链接文本。 - 文本:你不应该将文本放在图片中,如果是文本需要特殊效果,可以使用CSS达成。
即需要图片无法显示时,也可以提供一个可用的体验。
宽度和高度
你可以使用宽度和高度属性指定图片的宽度和高度。
1 | <img src="images/example.jpg" alt="this is a picture" width="400" height="341"> |
在图片没有加载出来的时候,浏览器会为要显示的的图片留下一定的空间。
这可以使页面加载的更加丝滑,不会出现页面长度不停变化的情况。
然而,你应该使用CSS改变尺寸而不是HTML。而且胡乱调整图片的尺寸,会出现图片模糊或扭曲等问题。
图片标题
使用<title>
给图片添加进一步的支持信息。
1 | <img src="images/example.jpg" alt="this is a picture" title="picture No.1"> |
当你鼠标停在图片上,会出现title信息。图片标题没必要包含主要信息,它有很多易访问性问题,即屏幕阅读器可能忽略图片标题,浏览器不会直接显示(除非鼠标停在图片上)。
解说图片
通过为图片搭配说明文字的方式来解说图片。
方法一:
1 | <div class="figure"> |
<p>
中包含你要说明的内容,这是一个方便使用CSS的风格。
但仍有一个问题,即从语义上讲,段落p和图片img没有联系。如果有10张图片以及搭配的说明文字,屏幕阅读器无法知道哪张图片应该匹配哪个说明。
方法二:
1 | <figure> |
使用HTML5的<figure>
和<figcaption>
元素——为图片提供了一个语义容器,在标题和图片之间建立清晰的联系。
说明文本和alt是完全不同的东西,它们存在的目的不同,alt是为了在显示不了图片的时候提供图片有必要说明的信息。而说明文本是在图片之外,一直可以显示的附加信息。
figure 元素里不一定是一张图片,它可以包含任何一个独立内容单元(几张图片、一段代码、音视频、表格等)。而 figcaption 元素包裹的说明文字描述了 figure 元素的内容。
- 用简单、易懂的方式表达意图
- 可以置于页面线性流的某处
- 为主要内容提供重要的补充说明
css背景图片
使用CSS把图片嵌入网站中。CSS中background-image
和其它background-*
属性是用来放置背景图片的。
1 | p{ |
相对于使用HTML插入图片,CSS可以更好地控制图片和设置图片的位置。
那为什么还要使用HTML插入图片?
这种CSS插入背景图片的方式只是为了装饰,这种方式插入的图片完全没有语义上的意义,没有备选文本,不能被屏幕阅读器识别。
视频和音频内容
使用<video>
和<audio>
元素添加音视频,并为视频添加字幕。
web中的音视频
传统web技术不能再web中插入音视频,所以一些Flash和Silverlight的专利技术很受欢迎,但它们有一系列的问题,无法很好地支持CSS和HTML特性,安全问题和可行性问题。
现在HTML5标准的提出,其中很多特性,包括<video>
和<audio>
标签,以及一些JavaScript和APIs可以用于控制音视频。
video元素
<video>
允许你轻松地嵌入一段视频
添加video
嵌入一段视频:
1 | <video src="example.webm" controls> |
其中的包围的属性和内容:
src
:
指向你要嵌入的资源。controls
:
使用controls来包含浏览器提供的控件界面,你也可以使用合适的 JavaScript API 创建自己的界面。至少包含开始、停止以及调节音量的功能。<video>标签内的内容
:
后备内容——当浏览器不支持video标签的时候,就会显示这段内容。
使用多个播放源
不同的浏览器对视频格式的支持不同,换个浏览器视频就不一定可以顺利播放。下面将介绍解决办法。
媒体文件的内容
像MP3、MP4、WebM这些术语叫容器格式,它们定义了构成媒体文件的音频轨道和视频轨道的存储结构,其中还包含描述这个媒体文件的元数据,以及用于编码的编码译码器等等。
一个格式为WebM的电影包含视频轨道、音频轨道和文本轨道。其中视频轨道还包含一个主视频轨道和可选的Angle轨道;有音频轨道包含英语、西班牙语和英语评论的音频轨道;文字轨道包含英语和西班牙语的字母轨道,如图所示:
在编解码器(codec)编码文件时,容器中视频轨道和音频轨道使用不同的格式,视频轨道使用视频编解码器进行编码,音频轨道使用音频编解码器进行编码。
不同的浏览器支持不同的视频和音频格式,以及容器格式。
例如:
- WebM容器通常包含Opus或Vorbis音频和VP8/VP9视频;基本所有现代浏览器都支持。
- MP4容器通常包含ACC以及MP3音频和H.264视频;同样在所有现代浏览器都支持。
- 老式的Ogg容器往往支持 Ogg Vorbis 音频和 Ogg Theora 视频;主要在Firefox 和 Chrome中支持,这个容器已经被更强大的WebM容器取代。
音频播放器将会直接播放音频文件,例如 MP3 和 Ogg 文件,这些不需要容器。
MP3文件实际上时存储在MPEG或MPEG-2容器中的MPEG-1音频层III(MPEG-1 Audio Layer III , MP3)音频轨道。
浏览器支持的媒体文件
上文所说的格式主要用于将视频和音频压缩成可管理的文件(原始的音频和视频文件非常大)。浏览器包含不同的codec,如Vorbis、H.264,将压缩的视频和音频转化成二进制数字。不同的编解码器和容器都有各自的优缺点,需要灵活选择合适的。
浏览器不是支持所有的的codec,所以得使用几个不同格式的文件来兼容不同的浏览器;如果你使用的格式都得不到浏览器的支持,你的媒体文件就不会播放。
要想你的媒体文件在不同平台和不同设备的浏览器都可以播放,这需要多种编码器组合使用,这是一个超麻烦的事,所以参考Choosing the right container来选择合适的容器格式;参考Choosing a video codec和Choosing an audio codec来选择编码格式。
对于一个浏览器,移动版和桌面版支持的格式可能不同,但它们都可以减轻媒体播放的处理负担。许多移动平台的浏览器能够借助底层系统的媒体播放器播放一些不支持的格式。
嵌入一个多个源的媒体,例如:
1 | <video controls> |
在上面例子中,src属性被移出video,而是放在单独标签<source>
当中。浏览器会检查source标签,播放第一个与自身codec相匹配的媒体。
每个source标签中,type
属性是可选的指定媒体类型的属性。浏览器可以通过检查这个属性跳过不支持的格式;如果没有指定type属性,浏览器会尝试加载每一个文件直达找到一个能正确播放的格式或者找不到正确格式。你应该在source标签中指定type,不然会消耗大量时间和资源。
其它video特性
HTML5中,video 有许多其他的特性。
1 | <video controls width="400" height="400" |
以下是新的特性:
- width 和 height
控制视频的大小。但视频会保持它原本的长宽比(纵横比),如果你设置的尺寸没有保持视频原始的长宽比,那么视频的边框将会拉伸,填充没有内容的部分,显示默认的背景颜色。 - autoplay
这个属性会使音频和视频的内容立即播放,即使页面的其他部分还没有加载完全。 - loop
这个属性使音频或视频文件循环播放。 - muted
使媒体播放时,默认关闭声音。 - poster
指向一个图像的URL,这张图片将会在视频播放前显示。通常用于预览或广告。 - preload
这个属性被用来缓冲较大的文件:- “none”: 不缓冲
- “auto”: 页面加载后缓存媒体文件
- “metadata”: 仅缓冲文件的元数据
从对象到iframe-其它嵌入技术
在网页中嵌入其他各种内容类型的元素:<iframe>
,<embed>
,<object>
。
很久以前,很流行在网络上使用框架创建网站——网站的一小部分存储于单独的HTML页面中。这些被嵌入在一个称为框架集的主文档中,它允许您指定每个框架能够填充在屏幕上的区域。
一小段时间之后(20世纪90年代末,21世纪初),插件技术变得非常受欢迎,例如 Java Applet 和 Flash ——这些技术允许网络开发者将丰富的内容嵌入到网页中,例如视频和动画等,这些内容不能通过HTML单独实现。嵌入这些技术是通过诸如<object>
和较少使用<embed>
的元素来实现的,当时它们非常有用。由于许多问题,包括可访问性、安全性、文件大小等,它们已经过时了。
最后,<iframe>
元素出现了(连同其他嵌入内容的方式,如<canvas>
,<video>
等),它提供了一种将整个web页嵌入到另一个网页的方法,看起来就像那个web页是另一个网页的一个<img>
或其他元素一样。<iframe>
现在经常被使用。
iframe详解
<iframe>
元素旨在允许你将其他Web文档嵌入到当前文档中,这很适合将第三方内容嵌入到你的网站。
在一个网页中插入MDN词汇表:
1 | <iframe src="https://developer.mozilla.org/en-US/docs/Glossary" |
以下是iframe的基本属性:
allowfullscreen
iframe可以通过 全屏API 设置为全屏模式。frameborder
如果设置为1,则会告诉浏览器在此框架和其他框架之间绘制边框,这是默认行为。0是删除边框。CSS可以更好实现相同的效果,border: none;
src
该指向嵌入文档的URL路径width
和height
指定 iframe 的高度和宽度备选内容
在<iframe></iframe>
标签之间包含备选内容,如果浏览器不支持 iframe ,就将显示备选内容。sandbox
该属性需要在较新版本的浏览器上工作,该属性可以提高安全性设置。
为了提高速度,在主内容完成加载后,使用JavaScript设置iframe的src属性。可以使你的页面更快的被使用,并减少你的官方页面加载时间(重要SEO指标)。
安全隐患
黑客试图恶意修改你的网页或欺骗人们做不想做的事情时,常把 iframe 作为共同的攻击目标。
单击劫持:是一种常见的iframe攻击,黑客将隐藏的iframe嵌入到你的文档中(或将你的文档嵌入到他们自己的恶意网站),并使用它来捕获用户的交互。来误导用户或窃取敏感数据。
在你使用iframe时,应注意:
- 只在必要时嵌入
只在完全需要时嵌入第三方内容。
“你怎么谨慎都不为过,如果你决定要做这件事,多检查一遍;如果是别人做的,在被证明是安全的之前,都假设这是危险的”
除了安全问题,还有知识产权问题。不要再网页上展示一些不属于你的东西。 - 使用HTTPS
HTTPS相较于HTTP增加了加密内容。数据保密性更强,更加安全。- 减少了远程内容在传输过程中被篡改的机会
- 防止嵌入式内容访问你的父文档中的内容。
使用HTTPS需要一个证书,对于你来说可能是昂贵的。你可以使用HTTP为父文档提供服务,但是绝不能使用HTTP嵌入第三方内容(最好情况,是你的用户的web浏览器给他们出一个警告)。
- 始终使用
sandbox
属性
一个允许包含在其里的代码以适当的方式执行或者用于测试,但不能对其他代码库造成任何损害的容器称为沙盒。
要想提高网页的安全性,你应该给嵌入的内容仅能完成自己工作的权限。
默认情况下,你应该使用不带参数的 sandbox 属性强制执行所有可用的限制。
当然,你可以添加权限给沙盒——sandbox=""
属性值内。 - 配置CSP指令
CSP 指 内容安全策略,它提供一组HTTP头,旨在提高HTML文档的安全性。
在<iframe>
安全性方面,你可以将服务器设置为 发送适当的X-Frame-Options
标题。这样做可以防止其他网站在其页面中嵌入你的内容。
embed 和 object 元素
这两个元素是用来嵌入多种类型的外部内容的通用嵌入工具,包括java小程序、Flash、PDF这样的插件技术,甚至视频、SVG和图像的内容。
插件 是一种对浏览器原生无法读取的内容提供访问权限的软件
插件和这些嵌入方法真的是一种传统技术,提及它们主要是为了以防您在某些情况下遇到问题。由于一些关系,Flash已经不受欢迎,PDF更倾向于被链接而不是被嵌入,其他内容也有更优秀、更容易的元素处理。
如果你需要嵌入插件内容:
<ambed> |
<object> |
|
---|---|---|
嵌入内容的位置 | src | data |
嵌入内容的准确媒体类型 | type | type |
由插件控制的框的高度和宽度(以CSS像素为单位) | height width |
height width |
名称和值,将插件作为参数提供 | 具有这些名称和值的 adhoc 属性 | 单标签<param> 元素,包含在内<object> |
独立的HTML内容作为不可用资源的回退 | 不支持 | 包含在元素object之后的param |
使用<embed>
元素嵌入Flash影片的示例:
1 | <embed src="whoosh.swf" quality="medium" |
swf——基于矢量的Flash动画文件格式
相当复杂,工作量很大。Adobe Flash工具生成的HTML往往更糟糕,它使用嵌入object元素的embed元素来覆盖所有的基础。
使用<object>
将PDF嵌入一个页面:
1 | <object data="example.pdf" type="application/pdf" |
最好用链接指向它们,而不是将其嵌入到页面中,以便它可以在单独的页面阅读或下载。
HTML和JavaScript可以轻松实现交互性,而不需要Java小程序或过时的ActiveX/BHO技术。你可以使用 HTML5 来满足媒体需求、矢量图形SVG、以及复杂图像和动画画布。
添加矢量图形
矢量图形拥有较小的文件尺寸,却高度可缩放,所以它们不会在镜头拉近或者放大图像时像素化。
什么是矢量图形
在网上,有两种类型的图片——位图和矢量图:
- 位图使用像素网格来定义——一个位图文件精确的的包含了每个像素的位置和它的色彩信息。流行的位图格式包括Bitmap(.bmp)、PNG(.png)、JPEG(.jpg)和GIF(.gif)。
- 矢量图使用算法来定义——一个矢量图文件包含了图形和路径的定义,电脑可以根据这些定义计算出当它们在屏幕上渲染时应该呈现的样子。SVG格式可以让我们创造用于Web的矢量图形。
下图左边是PNG,右边是SVG图像。
当你放大图片的时候,PNG明显模糊了,原因是PNG存储的是每个像素的位置和颜色,当PNG图片放大后,每个像素都会就被放大来填充更多的像素。而矢量图形是使用算法计算出图形的形状,会根据放大的倍数来调整算法中的值。
矢量图形相较于同样的位图,通常拥有更小的体积,因为它们仅需储存少量的算法,而不是逐个存储每个像素的信息。
SVG是什么
SVG是用于描述矢量图形的XML语言。它基本上是像HTML一样的标记,只是你有许多不同的元素来定义你要显示在图形中的形状,以及要应用于这些形状的效果。SVG用于标记图形,而不是内容。你可以使用<circle>
,<rect>
来创建简单图形——<feColorMatrix>
使用变换矩阵转换颜色,<animate>
矢量图形的动画部分,<mask>
在图像顶部应用模板。
使用以下代码创建一个圆和一个矩形:
1 | <svg version="1.1" |
对于一些简单的SVG,你可以手动编码;但对于一些复杂的图形,这会变得很复杂。为了创建SVG图像,大多数人使用矢量图形编辑器,如 Inkscape 或 Illustrator 。
SVG的优点:
- 矢量图象的文本可访问
- SVG可以很好的适应样式/脚本,因为图像的每个组件都是可以通过CSS或JavaScript编写样式的元素
SVG的缺点:
- SVG容易变得复杂,复杂的SVG文件会很大;复杂的SVG也会在浏览器中占用很长的处理时间
- SVG可能会比栅格图像更难创建
因此,光栅图像更适合照片那样复杂精密的图像
SVG的添加
添加SVG到页面有许多方法。
快捷方式-img标签
通过<img>
元素嵌入SVG,你只需要按照预期的方式在 src 属性中引用它。如果你的SVG没有固定的纵横比,你还应该提供 height 和 width 属性。
1 | <img |
优点:
- 快速,熟悉的图像语法与alt中提供的内置文本等效
- 可以通过在
<a>
元素嵌套<img>
,使图像轻松成为超链接
缺点:
- 无法使用JS操纵图像
- 如果要使用CSS控制SVG内容,必须在SVG代码中包含内联CSS样式(从SVG文件调用的外部样式不起作用)
- 不能用CSS伪类来重设图像样式(如:
focus
)
下面是引用SVG的的另一个例子:
1 | <img src="equilateral.png" srcset="equilateral.svg"> |
在src属性中引用PNG,使用srcset属性引用SVG,较旧的浏览器将加载PNG,支持SVG的浏览器将加载SVG。
使用SVG作为CSS背景图像:
1 | background: url("fallback.png") no-repeat center; |
旧版浏览器会加载PNG,而新版浏览器会加载SVG。和img方法一样,使用CSS背景图像插入SVG意味着它不能被JavaScript操作,会受到相同的CSS限制。
在html中引用svg代码
你可以将SVG代码放在<svg>
标签中,称之为SVG内联或内联SVG。
示例:
1 | <svg width="300" height="200"> |
优点:
- 将 SVG内联 减少HTTP请求,可以减少加载时间
- 为SVG元素分配class和id,并使用CSS修改样式,无论是在SVG中,还是HTML文档中的CSS样式规则
- 内联SVG是唯一可以让你在SVG图像上使用CSS交互和CSS动画的方法
- 可以将SVG标记包在
<a>
元素中,使其成为超链接
缺点:
- 只能在一个地方使用该SVG,多次使用会导致 资源密集型维护
- 浏览器不能像缓存普通图片一样缓存内联SVG
使用iframe嵌入svg
在浏览器中打开SVG图像,就像打开网页一样。
1 | <iframe src="triangle.svg" width="500" height="500" sandbox> |
缺点:
- iframe有一个回退机制,如果浏览器不支持iframe,则只会显示回退
- 只有当你的SVG和你当前的网页是同源的,你才能在页面上使用JS操纵SVG
响应式图片
响应式图片是一种可以在不同屏幕尺寸和分辨率设备上都能良好工作以及具有其它特性的的图片。响应式图片奠定了响应式web设计的良好基础,它是响应式web设计的一部分。
为什么要用自适应图片
在一个网页中,有一张页首图片,并且在页首图片下,还有一张内容图片。页首图片的跨度可能是整个页面的宽度,而内容图片会适应内容纵列的某处。
这个网页在宽屏设备上表现良好,例如笔记本电脑或台式电脑。
但是,当你尝试在一个狭小的屏幕设备上查看本页面时,页眉这张图片占据了屏幕的一大部分的高度,你很难看到在第一张图片内容里的人。
- 有一个改进的方法,在狭窄的屏幕上,你可以显示一张图片的包含了重要细节的裁剪版本(美术设计问题)。
- 在手机上显示网页,你没必要嵌入很大的图片。这是一个分辨率切换问题:位图有固定数量的像素宽和像素高,如果显示尺寸大于原始尺寸,一张较小的位图看起来会有颗粒感。
而且,没必要在比图片尺寸小的屏幕上显示一张大图,这会浪费带宽。理想的情况是根据访问网站时使用的设备,来提供不同的分辨率图片和不同尺寸的图片。同样的,有些设备有很高的分辨率,为了显示的更加优秀,可能需要超出你预料的更大的图像。
响应式图像技术,通过让浏览器提供多个图像文件来解决上述问题。比如使用包含多个不同分辨率的图片(分辨率切换);使用不同的图片以适应不同的空间分配(美术设计)。
创建自适应图片
我们可以专注于HTML的<img>
,使用HTML的响应式图片来解决这些问题。但是,网站页眉的图片仅仅是装饰性的,应该使用CSS的背景图片来实现。
分辨率切换-不同的尺寸
根据设备的不同,显示不同大小的图片。
这是指定唯一资源文件的img:
1 | <img src="image.jpg" alt="it's a picture"> |
我们可以使用两个新的属性——srcset
和sizes
——来提供更多额外的资源图像和提示,帮助浏览器选择正确的一个资源。
1 | <img srcset="elva-fairy-320w.jpg 320w, |
srcset 和 sizes 属性 有不同的属性值,每个值都包含逗号分隔的列表。列表的每一部分由三个子部分组成。
srcset 定义了我们允许浏览器选择的图像集,以及每个图像的大小:
- 一个文件名(elva-fairy-320w.jpg)
- 一个空格
- 图像的固有宽度(以像素为单位,320w)——这里使用的单位是w,而不是px。这是图像的真实大小,你可以检查电脑上的图片文件找到。
sizes 定义了一组媒体条件(例如屏幕宽度)并且指明当某些媒体条件为真时,什么样的图片尺寸是最佳选择:
- 一个媒体条件((max-width: 480w))。媒体条件描述了屏幕可能处于的状态,在这里,说的是“当可视窗口的宽度是480像素或更少”。
- 一个空格
- 当媒体条件为真时,图像将填充的槽的宽度(440px)
对于槽的宽度,你可以提供一个固定值(px, em)或者是一个相对于视窗的长度(vw)——不是百分比。
最后一个槽的宽度是没有媒体条件的,它是默认的,当没有任何一个媒体条件为真时,它就会生效。
当浏览器成功匹配第一个媒体条件的时候,剩下所有的东西都会被忽略,所以要注意媒体条件的顺序。
当浏览器加载图片时:
- 查看设备宽度
- 检查 sizes 列表中哪个媒体文件是第一个为真
- 查看给与该媒体的槽的大小
- 加载 srcset 列表中引用的最接近所选的槽大小的图像
如果浏览器以视窗宽度为 480px 来加载页面,那么(max-width: 480px)
的媒体条件为真,因此440px的槽会被选择,又因为elva-fairy-480w.jpg
的的固定宽度 480w 最接近 440px ,所以将被加载。
800px的照片大小为128KB而480px版本仅有63KB大小—节省了65KB。如果这是一个有很多图片的页面,使用这种技术会节省移动端用户的大量带宽。
老旧的浏览器不支持这些特性,它会忽略这些特征,并继续正常加载 src 属性引用的图片。
注意:在HTML中的
<head>
标签里,你将会找到这一行代码`:这行代码会强制的让手机浏览器采用它们真实可视窗口的宽度来加载网页。(有些手机浏览器会提供不真实的可视窗口的宽度,来加载比浏览器真实可视窗口宽度大的网页,然后再缩小加载的页面。)
分辨率切换-不同的分辨率
如果你想要图片支持 多种分辨率显示 且 图片的实际尺寸是相同的 ,你可以让浏览器通过 srcset 和 x 语法结合——一种简单的语法,来选择适当分辨率的图片。
1 | <img srcset="elva-fairy-320w.jpg, |
在这个例子中,下面的CSS会应用在图片上,所以它的宽度在屏幕上是320像素(也称为CSS像素):
1 | img { |
在这种情况下,sizes 并不需要——浏览器只是计算出正在显示的显示器的分辨率,然后根据 srcset 引用最适合的图像。
- 如果访问页面的设备具有低分辨率显示,一个设备像素表示一个CSS像素,elva-fairy-320w.jpg 会被加载(1x 是默认值,不需要写出来)
- 如果设备具有高分辨率,两个或更多的设备像素表示一个CSS像素,elva-fairy-640w.jpg 会被加载。
美术设计
美术设计问题 涉及要更改显示的图像以适应不同的图像显示尺寸。
例如,如果在桌面浏览器上的一个网站上显示一张大的、横向的照片,照片中央有个人;然后当在移动端浏览器上浏览这个网站时,照片会缩小,这时照片上的人会变得非常小。
这种情况需要在移动端显示一个更小的肖像图。<picture>
元素可以实现这个需求。
这是原始图像:
1 | <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"> |
让我们改用<picture>
。就像<video>
,<audio>
,picture 元素包含了一些<source>
元素,它使浏览器在不同的资源间做出选择,紧跟着的是最重要的元素是 img 。
1 | <picture> |
<source>
元素包含一个media
属性,这个属性包含一个媒体条件——第一个条件返回真,那么就会显示这张图片。在这种情况下,如果视窗的宽度为799px或更少,第一个source元素的图片就会显示;如果视窗的宽度是800px或更大,就显示第二张图片。srcset
属性包含要显示图片的路径。 source 可以使用引用多个图像的srcset属性,还有sizes属性。所以你可以通过一个 picture 元素提供多个图片。- 在任何情况下,你都必须在
</picture>
之前正确提供一个<img>
元素以及它的src和alt属性,否则不会有图片显示。当媒体条件都不返回真的时候,它会提供图片;或者浏览器不支持 picture 元素时,它可以作为后备方案。
你应该仅仅当在美术设计场景下使用media属性。当你使用media时,不要在sizes属性中也提供媒体条件。
现在有许多高质量的图像格式,但是浏览器对它们的支持参差不齐。因此,你可以在type
属性中提供MIME类型,减少浏览器选择codec的时间,快速拒绝不支持的文件类型。
1 | <picture> |
你可以在 srcset 和 sizes 中使用逗号分割的列表。
为什么我们不能使用 CSS 或 JavaScript 来做到这一效果?
当浏览器开始加载一个页面, 它会在主解析器开始加载和解析页面的 CSS 和 JavaScript 之前先下载 (预加载) 任意的图片。这是一个非常有用的技巧,平均下来减少了页面加载时间的20%。
但是, 这对响应式图片一点帮助都没有, 所以需要类似 srcset的实现方法。
因为你不能先加载好 <img>
元素后, 再用 JavaScript 检测可视窗口的宽度,如果觉得大小不合适,再动态地加载小的图片替换已经加载好的图片。这样的话, 原始的图像已经被加载了, 然后你又加载了小的图像, 这样的做法对于响应式图像的理念来说,是很糟糕的,是一种多余的、浪费带宽资源的行为。
- 美术设计:当你想为不同布局提供不同剪裁的图片——比如在桌面布局上显示完整的、横向图片,而在手机布局上显示一张剪裁过的、突出重点的纵向图片,可以用
<picture>
元素来实现。- 分辨率切换:当你想要为窄屏提供更小的图片时,因为小屏幕不需要像桌面端显示那么大的图片;以及你想为高/低分辨率屏幕提供不同分辨率的图片时,都可以通过 vector graphics (SVG images)、 srcset 以及 sizes 属性来实现。