8.2 媒体查询

媒体查询是CSS代码的容器,其中的CSS只在某些条件(比如,当前页面要被打印或者要显示在某种类型或尺寸的屏幕上)具备时才会应用。媒体查询可以用两种方式来写:@media规则和<link>标签的media属性。

安卓设备的屏幕大小千差万别,下面这个网页列出了针对iOS、安卓和Windows设备的所有媒体查询:http://pugetworks.com/blog/2011/04/css-media-queries-for-targeting-different-mobile-devices/

8.2.1 @media规则

第一种方式是@media规则,可以在样式表或<style>标签的CSS中包含媒体查询,比如:

  1. @media print {
  2. nav {
  3. display:none;
  4. }
  5. }

这条规则声明:如果当前页面要打印,那么就不显示nav元素。

大家注意,这里是把CSS规则嵌套在了一个@media规则中,乍一看似乎有点不太习惯。尽管可以把CSS规则嵌套在媒体查询里,但媒体查询本身却不能互相嵌套。下面再看一个假设的示例(倒是跟图8-1和图8-2中的例子关系更密切),其中涉及最大屏幕宽度。

  1. /*只在屏幕宽度不大于568像素时应用*/
  2. @media screen and (max-width:568px) {
  3. .column {float:none; width:96%; margin:0 auto;}
  4. }

对这个例子而言,如果页面是通过屏幕显示,而且该屏幕宽度不超过568像素,那么CSS就会取消带.column类的元素的浮动,让布局区块上下堆叠,且让该元素宽度为屏幕的96%,同时在屏幕上居中。

iPhone 4的屏幕分辨率为320×480,而iPhone 5的屏幕分辨率则为320×568(至少对浏览器和媒体查询来说是这么大,因为像素是翻倍使用的——物理像素在两个方向上都是这里值的两倍)。把max-width设定为较大的iPhone 5屏幕的最大宽度,可以保证布局各栏在所有iPhone中都不再浮动,而是上下堆叠。

想知道怎么在苹果视网膜(retina)屏和其他高分辨率屏上以恰当的分辨率显示图片?可以参考这篇文章:http://coding.smashingmagazine.com/2012/08/20/towards-retina-web/

简单地理解,就是相应设备必须是一块最大屏幕宽度不超过568像素的屏幕(比如浏览器或智能手机)。因此,这条规则就不会应用给1024×768像素的iPad。

下面我们再看一看如何在<link>标签的media属性里写媒体查询。

谈谈媒体查询

媒体类型 最常用的媒体类型如下所示。

  • all:匹配所有设备;
  • handled:匹配手持设备(小屏幕、单色、带宽有限);
  • print:匹配分页媒体或打印预览模式下的屏幕;
  • screen:匹配彩色计算机屏幕;
  • 其他媒体类型还有braille(盲文点字触觉反馈设备)、embossed(盲文分页打印机)、projection(投影仪)、speech(语音合成器)、tty(电话机屏幕等固定宽度字符栅格设备)和tv(电视机)。

要想详细了解这些媒体类型,请参考CSS 2.1标准:http://www.w3.org/TR/CSS2/media.html

当然,任意时刻浏览器窗口中只能使用一种媒体类型。媒体类型从IE6开始就得到支持了,但媒体特性到IE9以上才得到支持。一般来说这并不是问题,因为我们使用媒体特性多数情况下都是为了检测平板电脑或智能手机等现代设备。

媒体特性 媒体特性也就是媒体某一方面的特征,一般带有min-max-前缀。最常用的媒体特性如下。

  • min-device-widthmax-device-width:匹配设备屏幕的尺寸;
  • min-widthmax-width:匹配视口的宽度,例如浏览器窗口宽度;
  • orientation(值为portraitlandscape):匹配设备是横屏还是竖屏。

如果想通过媒体查询来根据用户对浏览器窗口的缩放重新调整布局,应该使用min-widthmax-width。要了解所有媒体特性,请参考CSS3标准:http://www.w3.org/TR/css3-mediaqueries/#media1

可以使用逻辑运算符andnotor及关键字allonly组合媒体类型和媒体特性。

其中,only关键字可以用来对不支持媒体查询的浏览器隐藏样式表。关于媒体查询中可以使用的逻辑运算符的详细信息,请参考这里:https://developer.mozilla.org/en-US/docs/CSS/Media_queries#Operator_precedence

这里有一篇关于媒体查询的扫盲文章,非常不错:http://www.javascriptkit.com/dhtmltutors/cssmediaqueries.shtml。至于要在IE8及以下版本的IE浏览器中使用媒体查询,可以使用腻子脚本Respond.js(参见本书附录末尾的“腻子脚本”)。

如果要通过媒体查询应用的CSS规则非常多,那么就可以考虑使用<link>标签的media属性设定条件,有选择地加载独立的样式表。你不会不知道吧,我们前面一直都是在使用<link>标签向HTML中链接样式表的。嗯,这个你应该知道。不过,你未必知道的是,通过在<link>标签的media属性中指定条件,可以有选择地加载样式表。

下面这个例子在前面介绍@media规则时展示过,但这次我们使用的是<link>标签的media属性。

  1. <link type="text/css" media="print" href="css/print_styles.css" />
  2. <link type="text/css" media="screen and (max-width:568px)" href="css/iphone_styles.css" />

结果都一样,即这里的CSS样式表会根据media属性中的指定的条件应用。而且,查看页面的如果是大显示器或iPad,则浏览器根本不会加载上面例子中的第二个样式表。第二个样式表只会被查看该页面的智能手机加载。那怎么使用媒体查询最直观呢?最直观的方式莫过于根据不同的断点来编写媒体查询。

要适配不同的设备,推荐Andy Clarke的320 and Up样板包:http://stuffandnonsense.co.uk/projects/320andup/

8.2.3 断点

断点(breakpoint)在这里指的是媒体查询起作用的屏幕宽度,其写法类似如下形式。

  1. @media screen and (max-width:640px) { /*CSS规则*/ }

在这里,断点是640像素宽。如果有设备的屏幕宽度等于或小于断点设定的宽度,那么后面的CSS就会起作用。

可能有人会使用断点去匹配特定设备的屏幕宽度,但我认为最重要的,还是在屏幕变小的情况下,通过简化布局来确保可用性。换句话说,不要简单地用断点去匹配设备宽度,而是可以从慢慢地缩小浏览器窗口开始,在发现当前布局不合适的时候再确定断点,然后编写新样式。不要针对某款具体的设备,而要为宽度在某个范围内的屏幕提供替代的布局,该布局对于范围内的设备都应该适用。

我在发现一个可以作为断点的布局宽度时,通过查看我的电脑上安装的Ambrosia Software的截屏软件SnapzPro X所显示的大小,就可以知道布局的像素宽度。

通过缩小浏览器窗口,能够直观地感受到当前布局在小屏幕上的效果。不过,毋庸置疑,必须还要在小屏幕设备上进行测试。平板电脑与小显示器尺寸接近,因此1000像素的断点(为屏幕小于等于1000像素的设备提供样式)适合平板电脑。在这样做之前,我们先讲一讲怎么取消iPhone和iPad中“缩小适应”的默认行为。

8.2.4 用<meta>标签设定视口

从图8-1和图8-2可以看出,iPad和iPhone会把适合大屏幕的网页缩小,以便在它们较小的屏幕上能看到网页的全貌。这是一个通用技巧,但对于手机——特别是iPhone来说,由于文字实在太小了,为了看清楚网页内容,肯定得用扩展手势放大页面,然后再来来回回地扫屏。如果你想让自己的页面布局适合这些小屏幕,首先就要覆盖这种自动缩小的设定。方法是在页面的<head>标签里添加一个<meta>标签:

  1. <meta name="viewport" content="width=device-width; maximumscale=1.0" />

这个<meta>标签告诉浏览器按照屏幕宽度来显示网页,不要缩小网页。虽然这样可以让布局以实际宽度显示,但在iOS设备(如iPad和iPhone)中却会引发一个已知的bug。关于这个bug及如何解决,本章后面再交待。

关于<meta>标签,其实还有很多内容值得深究,详细情况请参考这里吧:http://developer.android.com/guide/webapps/targeting.html