9.4.1 媒体查询
在早些时候,为了满足移动用户的需求,需要为移动设备专门建立一个额外的网站。随着响应式设计的出现,这种做法已经越来越少见了。
2010年5月25日,Ethan Marcotte在A List Apart上发表了一篇开创性的文章,在这篇名为Responsive Web Design的文章中,他将媒体查询、弹性网格布局、弹性图片这三种已有的开发技术整合起来,并命名为响应式Web设计(RWD,Responsive Web Design)。
响应式设计的理念是,页面的设计应当根据用户行为及设备环境,进行相应的响应和调整。有了响应式设计,一个网站只需要一个版本便能兼容多个终端,而不必为每个终端制作一个特定的版本,可以大大降低网站的成本。
媒体查询
媒体查询(Media Queries)是CSS3中提出的一个新概念,它允许为页面设置不同的媒体条件,并根据条件来应用相应的样式。媒体查询的基本语法为:
media_query: [only | not]? <media_type> [ and expression ]*
expression : (media_feature [: value]?)
可以看出,媒体查询主要包括三部分内容,分别是媒体类型(media_type)、媒体特性(media_feature)和关键字。
媒体类型
媒体类型(Media Type)是CSS2中就已经存在的一个常见属性,指的就是用户浏览网页的设备,如电脑显示器、打印机、投影设备,甚至盲文触觉反馈设备等。W3C共定义了10种媒体类型见表 9‑9。
属性 | 说明 |
---|---|
all | 所有设备 |
braille | 盲文触觉反馈设备 |
embossed | 盲文打印机 |
handheld | 小型或手提设备 |
打印机或显示屏设备上的打印预览模式 | |
projection | 投影展示设备,如投影仪、PPT |
screen | 显示屏设备 |
speech | 语音或音频合成器 |
tty | 固定间距的字符栅格设备,如电传打字机和终端 |
tv | 电视类设备 |
媒体特性
媒体特性就是媒体的属性,媒体查询允许针对不同的媒体特性,定义不同的样式。最常用的媒体特性是设备的视口宽度和屏幕宽度,但为了方便查阅,下面列出所有可供查询的媒体特性。
属性 | 说明 |
---|---|
width | 设备的视口宽度 |
height | 设备的视口高度 |
device-width | 设备的屏幕宽度 |
device-height | 设备的屏幕高度 |
orientation | 设备目前处于横向还是纵向状态 |
aspect-ratio | 设备视口的宽度和高度的比例。如,16:9的显示屏aspect-ratio:16/9 |
device-aspect-ratio | 设备的宽度和高度的比例 |
color | 设备每种颜色的位数。如,min-color:32会检测设备是否拥有32位颜色 |
color-index | 设备颜色索引表中的颜色值不能是负数。 |
monochrome | 单色帧缓冲区中,每个像素所使用的位数。值不能是负数。 |
resolution | 屏幕或打印机的分辨率。如,min-resolution:300dpi或min-resolution:118dpcm |
scan | 电视机的扫描方式,可以是progressive(逐行扫描)或interlace(隔行扫描) |
grid | 设备是网格的还是位图设备 |
上表中的所有特性,除 scan 和 grid 外,都带有 min 和 max 前缀,用于表示小于等于和大于等于某个值的情况。
媒体特性用逻辑表达式表示,格式跟CSS样式规则的格式非常相似。一个表达式是一个媒体特性和值对,中间用冒号隔开,每个表达式包裹在一对圆括号中。如:
(max-width: 480px)
一个表达式可以看作是一个提问,上述表达式就相当于在问“你的最大宽度是480px吗?”。由此可知,一个表达式的结果就是一个布尔值。因此,某些媒体特性(如,color、monochrome、grid等)就可以直接用作条件,而无需指定它的值。如,以下语句就表示所有彩色设备:
(color)
如果要同时检测多个特性,可以设置多个表达式,并用关键字 and 连接起来。因此,可以使用 min 和 max 前缀来创建一个查询范围。如:
(min-width: 360px) and (max-width: 480px)
这里对 width 应用了 min 和 max 来设定查询范围,就表示视口宽度介于 360 像素和 480 像素之间。
关键字
媒体查询中可以使用的关键字有and、only、not,and主要起连接作用,only 用来限定整个查询结果,not 用对整个查询结果取反。如果使用关键字 not 或 only,必须明确指定一个媒体类型,并且关键字必须位于整个媒体查询语句的开头。
1)and
关键字 and 用来把媒体类型和多个媒体特性的表达式组合起来,合并到同一条媒体查询中。只有当媒体类型和每个表达式的结果都为真时,查询结果才为真。如:
screen and (min-width: 700px) and (orientation: landscape)
媒体查询的结果是一个布尔值:要么为true,要么为false。只有当 and 连接的所有部分都为true,整条媒体查询语句的结果才为 true。
媒体查询也可以看作是对浏览器的提问。上述媒体查询首先会问“你是一块显示器吗?”,如果浏览器回答“是”,会继续问“你的最小宽度为700像素吗?”,如果浏览器回答“是”,再继续问“你的屏幕处于横向状态吗?”。只有当三个提问都回答“是”, 整条媒体查询语句的结果才为 true。
2)only
关键字 only用来限定范围,它将作用于整个查询结果。如:
only screen and (color)
就仅仅对彩色显示屏设备有效,对其他任何设备均无效。它等价于:
not (screen and (color))
3)not
关键字not用来对整个查询结果取反。如:
not (screen and (monochrome))
就表示除单色显示屏设备外的所有设备。它等价于:
not (screen and (monochrome))
而不是:
(not screen) and (monochrome)
除了单个查询外,也可以定义一个媒体查询的列表,列表之间用逗号隔开。如果列表中的任意一个媒体查询的结果为 true,媒体查询的列表的结果就为 true;否则,媒体查询的列表的结果就为 false。
媒体查询列表中的每个查询相互独立,一个查询中的操作符并不影响其它的媒体查询。因此,媒体查询列表能作用于不同的媒体类型和媒体属性。如:
(min-width: 700px), handheld and (orientation: landscape)
上述媒体查询列表中包含两个媒体查询,对于最小宽度为700像素的任何设备,或者横屏的手持设备,媒体查询列表的结果为 true,其他情况均为 false。
有了媒体查询,就可以使用它来构建响应式布局了。有两种使用媒体查询的方法:一种是使用 @media 规则,选择载入不同的CSS代码;一种是使用 <link> 标签的 media 属性,选择加载不同的样式表文件。
1)使用 @media 规则
使用 @media 规则,要在同一个CSS 文件中,根据不同的媒体条件,定义不同的样式。用户浏览网页时,浏览器会根据媒体查询的结果,选择应用哪一段CSS代码。
@media 规则的语法,是在 @media后,紧跟媒体类型和媒体特性,然后是一对大括号,在大括号中定义相应的样式规则。如:
@media screen and (max-device-width: 480px) {
/* 如果设备宽度 <= 480px,将会应用这里的 CSS 代码 */
}
@media screen and (max-width: 768px) {
/* 如果视口宽度 <= 768px,将会应用这里的 CSS 代码 */
}
根据样式的层叠性,样式表中后定义的样式,会覆盖前面的相同样式。因此,就可以在样式表的开头定义基本样式,来适应所有的设计,再使用媒体查询重写相应的部分,让不同的媒体条件应用不同的样式规则。
2)使用 <link> 标签的 media 属性
使用 <link> 标签的 media 属性时,针对不同的媒体条件,定义不同的样式表文件,浏览器会根据媒体查询的结果,加载不同的样式表文件。
<link rel="stylesheet" media="screen" href="reset.css">
<link rel="stylesheet" media="screen and (max-width: 480px)" href="phone.css">
<link rel="stylesheet" media="screen and (min-width: 768px)" href="screen.css">
这里定义了3个样式表文件reset.css、phone.css、screen.css,并让所有的显示屏设备都加载reset.css,让视口宽度小于 480px 的显示屏设备加载phone.css,让视口宽度大于768px的显示屏设备加载screen.css。
可以看出,使用第一种方法,要在同一个CSS 文件中,写好几遍 @media;使用第二种方法,要写好几遍 <link> 标签。两种方法的效果相同,可以选择自己喜欢的方式。
事实上,还可以是CSS的 @import 指令按条件引入其他样式表。如,以下代码对给视口最大宽度为 360px 的显示屏设备加载一个名为 small.css 的样式表文件。
@import url("small.css") screen and (max-width: 360px);
但是,使用CSS的 @import 方式会增加HTTP请求,这会影响页面的加载速度,因此并不推荐使用这种方法。
在媒体查询中,把设备宽度的临界点称作断点,并把媒体特性 min-width 和 max-width 对应的属性值称作断点值。
综上所述,媒体查询就是使用断点来创建媒体查询的条件,并为每个断点调用一个样式表文件(或样式代码),来实现在不改变页面内容的情况下,为不同的设备及不同尺寸的设备定制显示效果。
说明:让IE6~8支持媒体查询
虽然媒体查询已经被广泛使用,并得到所有现代浏览器的支持,但IE 9以下的老版本浏览器却不支持它。可以选择给老版本的IE添加垫片脚本,让它们支持媒体查询功能。
respond.js(https://github.com/scottjehl/Respond)是一个快速、轻量的 Javascript 工具,它会遍历页面上的所有 CSS 引用,并使用媒体查询分析 CSS 规则。然后,监控浏览器宽度的变化,并添加或删除与媒体查询匹配的样式,使原本不支持媒体查询的IE6-8 支持媒体查询的 min-width 和 max-width 特性。
respond.js的使用非常简单,只需在页面所有的CSS之后,使用IE条件注释,让IE6-8版本加载 respond.js 脚本即可:
<!--[if lt IE 9]>
<script src="respond.js "></script>
<![endif]-->
但需要注意,respond.js 无法解析CSS的@import指令。因此,建议在已有的样式表中追加媒体查询的样式。如,在样式表文件中,使用 min-width 或 max-width 定义媒体查询:
@media screen and (max-width: 480px) {
// 针对视口宽度小于 480px 的显示屏设备定义样式
}