构建 HTML5 应用程序

使用 CSS3 媒体查询构建响应速度更快的 Web

Brandon Satrom

下载代码示例

本文讨论 Internet Explorer 10 平台预览版。 所有信息均有可能发生变更。

几年前,我的一名客户希望我为他的那些喜欢研究技术的年轻用户群构建一个仅供手机使用的网站。 此项目对我们来说实际上是构建一个“iPhone 网站”,并且在设计上需要进行全面构思。 创建此类前沿移动应用程序令我们非常兴奋,我们认真地开始工作并获得了不错的进展,但当工作进展到考虑市场上的其他移动设备时,我们遇到了一些问题。 客户希望为他们的几乎所有移动设备提供支持。 我们就开始努力着手解决 Web 开发人员在尝试构建适合手机的体验时所面临的两个最重要的问题: 如何知道何时更改给定移动浏览器的体验,以及如何在需要时进行该更改?

响应式 Web 设计

这些问题是 Ethan Marcotte 创造的术语“响应式 Web 设计”(bit.ly/aO2cFa) 的核心。 响应式 Web 设计是指使用浏览器中的上下文线索来调整向用户呈现网站的方式和网站的运行方式。 它涉及使用符合用户在该设备上的交互预期的自定义优质体验来响应浏览器所呈现的信息。 如果正确的线索提供了有关所使用浏览器和设备的足够信息,则可以提供自定义设置,例如备用图像和可变布局。

过去,获得这些上下文线索的方法是分析浏览器所提供的用户代理字符串(这种做法称为浏览器或 UA 探查),然后使用该信息来确定如何继续操作。 我在 2011 年 9 月发表的文章“浏览器不应落伍: HTML5 采用策略”(msdn.microsoft.com/magazine/hh394148) 中介绍了 UA 探查。 正如我在该文中指出的,浏览器探查不可靠,并且实质上已被功能检测所取代,后者可帮助您根据可用功能而不是根据给定浏览器和版本做出有关标记、CSS 和 JavaScript 的决策。

在响应式 Web 设计的上下文中,所有新型桌面和主要移动浏览器均支持一项称为“媒体查询”的功能,它是扩展了 CSS 2.1 中引入的媒体类型想法的 CSS3 模块 — 能够为打印、屏幕等指定备用样式表,并能够确定访问网站的设备的一些物理特征。 类似于使用功能检测的基本原理,媒体查询允许您着重获取当前访问者的正确上下文线索,然后您可以使用这些线索来相应地调整提供的体验。 媒体查询的功能是为样式表提供此类线索。

在本文中,我将大致介绍媒体查询 CSS3 模块。 我将简单讨论其语法和用途,然后演示一个利用媒体查询为联机照片库构建适合在 Smartphone 和平版电脑上显示的视图的简单示例。 最后,我将分享一条对所有形式的移动开发都很重要的提示,然后总结有关媒体查询侦听器的简要讨论。媒体查询侦听器是一个单独的万维网联盟 (W3C) 规范 (bit.ly/wyYBDG),它提供了通过 JavaScript 对媒体环境变化做出反应的 API。 在本文结束时,您应该具有仅使用 CSS 和一些量身定制的样式创建响应式网站和应用程序的坚实基础。

CSS 媒体查询

正如前面提到的,CSS 2.1 当前支持基于“媒体类型”声明 (bit.ly/xhD3HD) 的依赖媒体的样式表。 以下标记说明如何使用媒体类型来指定条件样式表:

<link rel="stylesheet" type="text/css" href="main.css" media="screen" />
<link rel="stylesheet" type="text/css" href="print.css" media="print" />

在设置这些元素后,如果在打印预览模式下加载页面,则网站将加载与默认(或“屏幕”)样式表不同的样式表。 虽然此功能很有用(但在过去未充分利用),但它没有提供用于构建真正的响应式网站的任何有用的上下文线索。 虽然媒体类型规范详述了 10 种媒体类型的用法,但浏览器供应商从未完全采用所有这些指定的类型。

而“media”属性奠定了坚实的基础,W3C 决定在其上构建媒体查询 (bit.ly/zbIeDg)。 在您指定媒体类型(例如打印、屏幕或所有类型)时,媒体查询将允许您向媒体属性中添加一些表达式,用以检查某些媒体功能(例如当前设备的宽度、高度、方向,甚至屏幕分辨率)是否存在。 下面的示例在媒体类型为屏幕、设备宽度至少为 800 像素时加载 main.css 样式表:

<link rel="stylesheet" media="screen and (min-width: 800px)" href="main.css" />

媒体查询的内容位于括号内。 左侧指定要测试的属性 (width),并带有 min- 或 max- 可选修饰符,右侧指定该属性的值。 如果所讨论的设备或浏览器的屏幕宽度至少为 800 像素,将应用 main.css 中的样式。 否则,不应用这些样式。 此示例说明媒体查询如何为开发人员提供可用于创建响应式网站和应用程序的上下文线索。

开始使用

如上所述,目前所有主要浏览器的最新版本均支持 CSS3 媒体查询 (bit.ly/wpamib),因此您现在应该可以轻松地使用它们。 可采用三种方法对网站使用媒体查询。 第一种方法是有条件地加载整个样式表,如上一个示例中所示。 第二种方法是在样式表中使用 @import 指令。 下面是相同的测试,但这次使用 import 指令:

@import url("main.css") screen and (min-width: 800px);

就像在前一个示例中一样,此语句将计算当前设备的宽度,如果它至少为 800 像素,则加载 main.css 并应用其样式。

最后,您可以通过 @media 指令在 CSS 中内嵌使用媒体查询,如下所示:

@media screen and (min-width: 800px) { ...
}

在此示例中,不在单独的文件中定义样式,而是将它们内嵌在现有样式表中,并使用媒体查询包装它们,确保仅在适当时应用这些样式。

现在让我们来看看实际的媒体查询,先看一个简单的示例。 如果您希望在家中尝试它,可以查看本文的示例源代码,或打开您喜欢的 IDE 或文本编辑器并添加图 1 中的标记。

图 1 HTML 文档示例

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="media.css">
  </head>
  <body>
    <article id="small">This is a small screen</article>
    <article id="medium">This is a medium screen</article>
    <article id="large">This is a large screen</article>
    <article id="landscape">...
and you're in landscape mode...</article> 
  </body>
</html>

接下来,在同一文件夹中创建一个名为 media.css 的样式表,并添加图 2 中定义的样式。 请注意,我在文件底部定义了所有 @media 指令;您可能希望在样式表中执行相同操作。 如果您选择在标记中定义多个样式表,则还需要将特定样式表的 <link> 元素放在主样式表之后。 由于 CSS 的级联行为,特定于媒体的规则将可能需要取代主要规则,并应适当地进行定义。 您将注意到我为文章和正文元素定义了样式,然后为我希望支持的每种体验定义了媒体查询(及其相关规则)。 小于 480 像素的屏幕将获得一组附加样式;在 480 像素和 1024 像素之间的屏幕将获得另一组样式;大于 1024 像素的屏幕将获得第三组样式。 我还添加了一个方向查询,并且将在设备处于横向模式时应用另一组样式。

图 2 使用 @media 指令内嵌定义的 CSS 媒体查询

article {
  display: none;
}
body {
  font-size: 24px;
  font-weight: 800;
  color: white;
}
@media screen and (max-width: 480px) {
  body {
    background-color: #ff2a18;
  }
  #small {
    display: inline;
  }
}
@media screen and (min-width: 480px) and (max-width: 1024px) {
  body {
    background-color: #00ff00;
  }
  #medium {
    display: inline;
  }
}
@media screen and (min-width: 1024px) {
  body {
    background-color: #0000ff;
  }
  #large {
    display: inline;
  }
}
@media screen and (orientation: landscape) {
  body {
    background-color: #ff7f00;
  }
  #landscape {
    display: inline;
  }
}

在您创建了图 1 中的页面和图 2 中的样式表之后,即可在任何浏览器中打开该页面。 测试媒体查询十分简单;没有移动设备也可以进行测试。 只需调整浏览器窗口的大小,并观察文本和背景颜色如何随可见窗口的上下文的变化而变化。

现在,我们已了解媒体查询的基础知识,接下来让我们进一步演练一个更真实的示例。 在此示例中,我将向联机照片库中添加媒体查询,以便可以支持 Smartphone 和平板电脑。 您可以在 archive.msdn.microsoft.com/mag201204HTML5 中找到此示例的代码,它使用的是 WebMatrix (webmatrix.com) 附带的照片库模板。

如果您在移动或平板浏览器中打开此页面,您将注意到该页面“缩小”了,并且难以查看或阅读,如图 3 所示。 使用几个媒体查询和一些其他技巧,我们无需使用新标记或任何种类的浏览器探查即可创建量身定制的体验。

Mobile View Without Media Queries
图 3 没有使用媒体查询的移动视图

在为此示例创建的 desktop.css 文件的底部,首先添加媒体查询指令和条件。 因为我当前讨论的是最小屏幕,所以我将创建以下定义:

@media screen and (max-width: 480px) {}

现在,在该定义中,让我们创建一些规则来为较小屏幕调整图像大小并重新定位图像。 这些规则如图 4 所示。

图 4 针对移动设备修改样式

body {
  min-width: 120px;
  max-width: 320px;
}
h1 {
  font-size: 1.5em;
}
img {
  width: 250px;
  height: 187.5px;
}
ul.thumbnails li {
  width: 265px;
    height: 200px;
    line-height: 200px;
}
ul.thumbnails li span.image-overlay {
    width: 265px;
}

如果您在添加这些样式后刷新该页面,应看到类似于图 5 中所示的内容。 图像看起来不错,但主导航菜单未对齐。 另外,库使用 CSS :hover 伪选择器来显示有关每个图像的其他信息,如图 6 中所示。 因为此用户体验在悬停事件不常见的环境(Smartphone 和平板电脑)中没什么意义,所以我们还需要通过其他方法来呈现页面的这部分内容。 我们将通过在当前 @media 指令中添加图 7 中的样式来实现此目的。

Mobile View with Improved Images
图 5 包含改进的图像的移动视图

An Image with the Hover Effect Applied
图 6 应用了悬停效果的图像

图 7 适合在移动设备显示的导航和图像信息的样式

#banner {
  height: 110px;
  background: #eaeaea;
}
#menu li {
  display: block;
  margin-top: 3px;
  margin-bottom: 3px;
}
#menu li.tags a,
#menu li.galleries a,
#menu li.account a {
  background: none; 
}
#menu li.login {
  display: none;
}
ul.thumbnails li span.image-overlay {
  display:block;
  position: absolute;
  top: 0;
  left: 0;
  line-height: normal;
  width: 515px;
    padding: 5px;
}
ul.thumbnails li {
    background: #f3f6f7;
    border-color: #dbe2e5;
    border-radius: 7px;
    box-shadow: 0px 0px 20px 5px #A9A9A9;
}

现在,如果您在浏览器中刷新页面,应看到整齐的导航菜单,以及以前在发生悬停事件时显示的信息,类似于图 8

The Gallery with Better Navigation and Image Boxes
图 8 具有较好的导航和图像框的库

到目前为止,我们已经为库创建了桌面视图,拥有一个相当好的移动版本,并且我们所需要做的只是添加几条额外的 CSS 规则。 让我们进一步添加对大于 480 像素而小于 1024 像素的屏幕的支持 — 平板电脑。

如果您在桌面浏览器中查看照片库并将大小调整到小于 1024 像素(图 8 中所示屏幕),您将注意到许多图像被剪切掉了。 因为平板设备通常具有较大的屏幕,所以应该在库页面上呈现较大的图像。 因此,让我们为平板电脑大小的设备添加其他媒体查询:

@media screen and (min-width:480px) and (max-width:1024px)

在联机源中,我将一些 Smartphone 规则重构为一组适用于所有非桌面设备的样式,因此我只需为平板视图设置与文档、图像和缩略图大小相关的那些样式,如图 9 中所示。

图 9 适合在平板电脑上显示的视图的样式

body {
  min-width: 480px;
  max-width: 800px;
} 
img {
  width: 500px;
  height: 375px;
  align: center;
} 
ul.thumbnails li {
  width: 515px;
    height: 390px;
    line-height: 200px;
}

现在刷新平板视图浏览器中的屏幕,您将看到类似于图 10 的内容。 我们现在的目标是多个屏幕大小,进而是多种设备,而我们只需花些时间来创建一些备用样式。

Photo Gallery, Tablet-Friendly View
图 10 适合在平板电脑上显示的照片库视图

移动优先

在总结有关媒体查询的此次讨论之前,我希望和大家分享一条提示,它并不仅仅针对媒体查询的使用,而是在进行任何种类的移动 Web 开发时都很重要。 具体而言,您应该首先设置视区和进行相关设计以实现移动优先。

如果您在我在本文中演练媒体查询时始终进行编码,您可能会在 Smartphone 或 Smartphone 仿真程序中查看页面时发现一个小问题: 在一些设备上,“缩小”效果不起作用,即使是在应用条件规则后依然如此。 发生这种情况是因为移动浏览器会尝试“优化”较小屏幕上的体验,这对并不面向移动用户的网站很有帮助。 但对于此网站,此优化不会发生,您的优先选择是将单个 <meta> 标记添加到页面的 <head> 中来重写此行为,如下所示:

<meta name="viewport" content="width=device-width">

现在,如果您刷新页面并正确定义了媒体查询,则应该看到规则生效了。

您可能还注意到以下情况:在照片库示例中,我向现有网站中添加了移动体验。 作为熟悉媒体查询的开发人员,您也可能在开头执行此操作。 不过,在设计和开发网站及应用程序时强调“移动优先”将成为一种越来越重要的趋势。 正如字面上的意思一样,移动优先是指优先考虑用户的移动体验,而不是事后产生的想法(过去常常如此)。 如果您知道在过去两年中,Smartphone 和平板电脑销量已超过 PC 销量,并且移动浏览市场现在已占据所有 Web 浏览市场的一半以上,您就会明白其中的重要意义。 除此之外,移动优先的理念鼓励实现“渐进增强”,以便通过基本(通常仅文本)体验构建网站,并通过逐步为网站提供增强功能来更好地服务于各种浏览器和设备。 若要了解有关移动优先方法的详细信息,我强烈建议大家阅读 Luke Wroblewski 撰写的同名书籍(可从 bit.ly/zd9UWT 上购买该书)。

媒体查询侦听器

作为对 CSS3 中媒体查询支持的扩展,CSS 工作组希望添加 JavaScript API,以使开发人员能够在运行时评估媒体查询并侦听媒体查询条件中的运行时更改。 这些 API 记录在 CSSOM 视图模块规范 (bit.ly/w8Ncq4) 中。 图 11 显示了从 JavaScript 内部执行媒体查询并创建侦听器的示例。

图 11 使用媒体查询侦听器

listener = window.msMatchMedia("(min-width: 480px)");
evaluate(listener); // Perform an initial evaluation
listener.addListener(evaluate); // Evaluate each time the width changes
 function evaluate(listener) {
   if (mql.matches) {
    expandCommentList(); // Screen is at least 480px
   } else {
     shrinkCommentList(); // Screen is smaller
   }
 }

在设备的视区可能在运行时发生变化的情况下(例如,当 Smartphone 和平板电脑上的视图方向发生更改时),侦听器可能相当有价值。 使用媒体查询侦听器,您不仅可以从 CSS 中,还可以从脚本中响应这些更改。 CSSOM 视图规范目前处于工作草案状态,但 Internet Explorer 10 Platform Preview 提供了对媒体查询侦听器的支持,因此您可以在 Internet Explorer Test Drive (bit.ly/gQk7wZ) 上试用它。

在 Web 应用程序中支持多种平台、屏幕和体验的功能在过去几年中有了很大改进。 而在过去通常会创建特定于设备的网站版本,但移动设备的发展很快使设备目标设定变得不可行。 幸运的是,跨所有主要桌面和移动浏览器引入 CSS3 媒体查询意味着您现在可以使用对提供针对各种设备量身定制的体验确实重要的上下文线索,而且全部通过条件 CSS 来实现。 要了解有关 CSS3 媒体查询的详细信息,建议大家查看 Peter Gasston 撰写的杰出文章“The Book of CSS3”(No Starch Press, 2011) 中有关媒体查询的章节。 有关借助媒体查询提供的绝佳体验库,请查看媒体查询网站。 我希望本文为您提供了立即开始构建量身定制的体验的足够信息。 我期待看到您创建的了不起的体验!

Brandon Satrom 是 Kendo UI (kendoui.com)(Telerik 提供的 HTML5 和移动工具集)的产品经理。 他的博客是 userinexperience.com,您可以通过 Twitter twitter.com/BrandonSatrom 关注他。

衷心感谢以下技术专家对本文的审阅: John BoxSharon NewmanJacob Rossi