CSS-Windows8-应用开发教程-一-

94 阅读1小时+

CSS Windows8 应用开发教程(一)

原文:CSS for Windows 8 app development

协议:CC BY-NC-SA 4.0

零、简介

image 注意世界上的网络开发者数量巨大,这些开发者中的每一个人现在都是 Windows 8 的开发者——目标是有史以来最大的设备市场。

你是网页开发者吗?我是。我在 1994 年开始对网页进行逆向工程,从那以后我就被这个平台深深吸引住了。它从一开始就受到限制,但即使在大约二十年后的今天,它仍然吸引着开发者和消费者。我使用非常优雅和强大的 XAML(微软自己的用户界面(UI)技术)的经历偶尔会提醒我 HTML 的局限性,但我只是不断回到 web 堆栈,它具有开放和宽容的语法以及遍布全球的影响力。

也许你有一些网络技术的经验,你已经准备好为 Windows 8 用户编写一个应用程序。您需要掌握三种核心 web 技术:用于文档结构的 HTML(超文本标记语言)、用于布局和样式化这些文档的 CSS(级联样式表)以及用于实现应用程序逻辑的 JavaScript。这是一本关于 CSS 部分以及 CSS 在 Windows 8 应用开发中如何表现的书。无论您是否有 CSS 经验,您都将了解如何使用这种无处不在的样式语言。

我猜你至少对 Windows 8 有点熟悉。微软极受欢迎的 Windows 操作系统的最新版本是一个非常有趣的版本。这很有趣,因为它非常不同,因为开发人员可以使用一些不同的技术来开发应用程序,包括 HTML、CSS 和 JavaScript——我喜欢称之为 web 堆栈。

使用 Windows 8,您可以使用 web 堆栈创建应用程序,它们将在操作系统上本地运行。他们可以访问设备的传感器和其他本机工具,甚至可以进行硬件加速。

我想强调的是,我不希望这仅仅是一本技术参考书。当然,有事实需要传递,但比仅仅传递事实更重要的是传递一个概念。如果你只对 CSS 标准的定义或者 API 的语法感兴趣,你可以很容易地在网上找到。然而,在我看来,开发是教育和体验的一部分,也就是说,经历了足够多的成功和不成功的实现,从而真正学到了在线文档无法传达的东西。

顺便说一下,发展有第三个部分——灵感。你真的必须热爱你正在做的事情,并对你要去的地方有一个愿景,这必须在你身上产生足够的兴奋,以帮助你度过艰难的时期。如果你没有发现自己熬夜或早起写代码,那么你应该问问自己这是否真的是你的领域。

所以,这不仅是一本关于 CSS 和 Windows 8 的书,也是一本关于风格的书。可以把它看作一本关于生产力和美感,以及通过富有表现力的语法达到这些目的的书。

这本书的一个独特之处是,在整个过程中,我会指出标准属性和模板对 Windows 8 应用程序有没有帮助。我还将指出微软特定于供应商的属性和值,它们将为您增添魅力。您还将了解由 WinJS 库提供的 Windows 8 控件的内部结构,以及您需要知道哪些类名,以便能够正确地设计它们的样式。

既然你已经拿起了一本关于 Windows 8 中 CSS 的书,我想你很有可能正在编写一个应用程序。也许这个应用是你的创意,你真的希望看到它在市场上取得成功。如果是这样的话,那就太好了,因为你的应用程序成功的首要标准是用户的使用体验。你可能听说过这叫做 UX(用户体验)。当用户的体验让他兴奋,因为它节省了他的时间,给他带来了信息或见解,甚至只是因为它看起来像好的艺术而让他兴奋,他通常不愿意向你这个作者支付真金白银,他愿意高度评价和推荐你的应用程序。

微软在 Windows 8 中实现网络堆栈方面迈出了一大步。我认为这是朝着正确方向迈出的一步,而且我认为他们在如何做到这一点上非常明智。微软现在明白了,我们身处一个厌恶所有专有事物的世界,这是有充分理由的。我们不想拘泥于一种解决问题的方式。我们需要一般的技能和大量的选择。我们也不想与一家公司联姻,而是希望使用基于许多公司合作产生的标准的技术。

独立的标准是一件好事——事实上是一件伟大的事情,这就是为什么全世界都喜欢 web 栈。开发人员通常会选择开放标准,即使与专有的替代方案相比,最好的实现有所欠缺。

微软已经使用支持 Internet Explorer 10 的相同引擎来支持使用 web 堆栈制作的 Windows Store 应用程序。这意味着,几乎没有例外,如果你的标记和 CSS 在 IE10 中工作,它将在你的 Windows 应用中工作,反之亦然。

image 注意在实现 web stack 的过程中,微软已经彻底地遵守了标准。

当 HTML、CSS 或 JavaScript 对某个特性有了标准时,它就会被采用,通常,当某个特性不存在时,就会向 W3C 推荐一个标准。当无法在合理的时间内实现推荐的标准时,可以通过行业标准的特定于供应商的标记、属性和值来添加扩展功能。即使是最严格的标准也总会有漏洞,事实上供应商可以用他们自己的一些属性来填补这些漏洞是非常好的。更好的是,这些标签、属性和值都有前缀,这样它们就可以与标准区分开来。

例如,在 CSS 中,属性和值以破折号(-)开头,后跟特定于供应商的标识符、另一个破折号,最后是属性名。微软的特定于供应商的标识符是 ms,所以特定于供应商的标签的一个例子是 ms-grid。

开发人员喜欢他们的工具,我认为您很有可能已经安装并运行了您选择的工具。如果您是开发、web 开发的新手,或者只是在寻找一些关于使用什么来创建和维护 CSS 的指导,那么 Visual Studio 是不二之选。

Visual Studio 是世界上最强大和最流行的 IDE(集成开发环境)之一,这是有充分理由的。最新版本名为 Visual Studio 2012,你可以从微软网站http://aka.ms/win8downloads获得 Windows 8 的免费版本——Visual Studio Express 2012。这个快速版没有专业版的所有功能,但它拥有创建 Windows 8 应用程序所需的一切。

无论您是使用 HTML/JS 处理 web 应用程序还是 Windows 8 应用程序,Visual Studio 都为 CSS 提供了出色的支持。您将获得 IntelliSense 支持,它建议属性名和有效值,您还将获得一些其他有用的功能,如当您指定 CSS 颜色时呈现的字形。

Visual Studio 并不是您工具箱中的唯一工具。你也有混合物。不管你有 Visual Studio 的免费速成版还是付费版,Blend 都在同一个安装中附带了 Visual Studio。

Blend 和 Visual Studio 都是应用构建机器。你可以在这两种工具中从头到尾创建一个应用程序,但是 Blend 更像是一个设计者友好的工具,而 Visual Studio 更像是一个开发者友好的工具。您可以同时使用这两种文件,并且可以并排使用,因为它们都处理同一种项目文件。因此,如果你想要一些设计帮助,打开 Blend,如果你想做一些调试或编写一些重要的代码,打开 Visual Studio。

现在是时候深入研究 CSS 并发现使用它来设计 Windows 8 应用程序是多么有趣。

一、Windows 8 设计

image “现在和以前完全不同了”(巨蟒剧团)

重新构想的 Windows

毫无疑问,你听说过 Windows 8 被称为“Windows reimagined ”,你根本无法否认 Windows 8 和之前的 Windows 版本之间的范式转变有多么巨大。

我清楚地记得我第一次使用 Windows 8 时,试图抓住关于使用屏幕边缘和角落的概念,从新的用户界面识别桌面,从 Charms 栏在应用程序内搜索,甚至只是重新启动系统!

从第一个屏幕开始,对旧模式的背离就很明显。图 1-1 显示了用户登录 Windows 8 时看到的内容。

9781430249832_Fig01-01.jpg

图 1-1 。Windows 8 中的开始屏幕

把这个和图 1-2 对比一下,这是我们刚登录 Windows 7 后看到的。

9781430249832_Fig01-02.jpg

图 1-2 。Windows 7 中显示开始菜单的桌面

开始屏幕取代了开始菜单。眼球追踪研究证明,一旦用户打开 Windows 7 中的开始菜单,绝大多数人都不会看屏幕上的其他地方。全屏专用于启动体验的概念非常有意义。将开始屏幕视为一个应用程序,并了解 Windows 如何创建身临其境的开始体验。

事实上,在 Windows 8 带来的所有变化中,我认为与我们作为应用程序设计师最相关的是用户对其任务和内容的沉浸感。Windows 8 把屏幕的每一个像素都奉献给了你的应用,你的应用独自站在舞台上接受用户的尝试和评判。

你不需要走很远就能找到一个很好的应用程序的例子,它具有沉浸式的体验。图 1-3 中内置的地图 app 就是一个很优秀的。

9781430249832_Fig01-03.jpg

图 1-3 。地图应用很好地展示了 Windows 8 应用的沉浸感。毫无疑问,屏幕上的每个像素都是应用程序专用的

通过 Windows 8,微软带给我们的不仅仅是一个好的设计,还有一个好的设计框架。微软不仅提供了一种应用开发语言,还提供了一种 ?? 设计语言 ??。这种设计语言被完整地记录下来,并成为你的应用程序设计的基础。

Windows 8 的设计语言记录在http://design.windows.com。MSDN 强大的开发者网站的这一部分专注于一个伟大的应用程序所要求的整个设计过程。这包括对以下事项的建议:

  • 界定你的应用范围,帮助你决定你的应用擅长什么
  • 你的应用程序的盈利策略
  • 左边距的建议大小
  • 命令在应用程序栏中的位置

设计你的应用程序排除了你对用户界面语言的选择。你也可以使用微软的 XAML 语言实现好的设计,但是我们将使用 HTML 和 CSS。我们将首先进行设计,然后实现好的设计。有些设计原则一开始可能看起来有点深奥,但是看看它们能提供什么指导是很重要的。不要担心,因为当我们学习如何实现我们的好设计时,我们将在本章的结尾得到更多的具体内容。

我们将通过观察设计良好的应用程序的一些特征来探索良好的 Windows 8 应用程序设计。

出色的 Windows 8 应用程序设计的特点

http://msdn.microsoft.com/en-us/library/windows/apps/hh464920.aspx的 design.windows.com 网站中列举了一个设计良好的 Windows 8 应用程序的一些特征。在这一章中,我将一步一步地介绍这些特质,就像它们在微软的网站上呈现的那样,并且用我自己的观点和经验来逐一剖析它们。

使用微软设计风格

如果你从关于 Windows 8 设计的一章中学到一个概念,可能是这个: Windows 8 设计就是让用户沉浸在他们的内容中。

什么是内容?应用程序的内容是用户启动应用程序的原因。对于一个财经 app 来说,内容就是股价或者一篇财经文章。对于一个社交应用来说,内容就是朋友或者对话。对于照片应用程序来说,内容就是照片。

Windows 8 基本上只是显示内容,而不是用关于内容的辅助信息来包装内容。当你在看一张照片时,你通常只会看到一张从屏幕的一边延伸到另一边的照片,而当你在社交网络上查看朋友的个人资料时,你会看到一个专用于该朋友基本信息的视图。

这不是用户界面发展的下一步。这与当前的趋势有所不同,当前的趋势是将所有内容都塞进一个屏幕,这样只需点击一下鼠标就能看到所有内容。视图设计表面 25%甚至更少的部分用于内容本身并不罕见。然而,这种趋势的缺陷是,当一个视图中添加了太多内容时,它就不能达到让用户的生活更轻松的目的,因为单个部分失去了它们的意义,而所有部分都失去了用户。

屏幕上不是内容的都是 chrome 。镀铬是汽车行业的一个术语,添加抛光的金属部件来吸引买家,即使它们在车辆功能中不起作用。单纯的审美没有错,但 chrome 在应用程序中的问题是,它会分散用户对其内容的注意力,从而影响应用程序。

Windows 8 的设计原则试图将内容放在 chrome 之前。并不是说 chrome 永远不会存在,而是一个 app 设计师要小心翼翼的介绍。你的应用应该总是优先考虑内容,排除干扰。请注意图 1-4 中 Windows 8 中的 Xbox Music 应用程序如何只显示内容。

9781430249832_Fig01-04.jpg

图 1-4 。Windows 8 应用将 100%的空间用于内容

将 chrome 添加到视图中有三个经典原因:导航、交互和布局。然而,这些对应用程序的可用性起着重要的作用,所以我们必须替换它们,而不是删除它们。让我们来看看这些类型的 chrome 的功能是如何在不影响内容的情况下实现的。

航行

静态导航有罪,造了很多 chrome。我们都熟悉标准的网站模型,在页面的顶部有一个标题,在页面的下方或左侧有导航链接。

为了避免点击,许多人甚至在导航菜单中填充多级悬停激活弹出菜单,甚至包括整个网站结构的树形视图。选项卡是另一种流行的现代形式的静态导航。

静态导航的问题是,它不符合我们应用程序的主要目的,即传递用户的内容。静态导航是关于用户下一步可能想去哪里的信息,但它不会告诉用户他们在哪里,因此它不是 Windows 8 应用程序中的推荐做法。那么我们如何促进导航呢?我们通过设计一个清晰的信息层次结构来实现这一点,该层次结构可以自然地将用户引导到下级或后续内容。

Windows 8 应用有两种主要的推荐导航模式。我将简要介绍每一个,但在http://msdn.microsoft.com/en-us/library/windows/apps/hh761500.aspx#hierarchical_system会读到更多。

三层导航

第一个模型是三层的分层导航模型。在这个模型中,所有的网站内容都存在于三个层次中——中心*、部分细节。对于一个内容驱动的应用程序来说,这种导航模型的层级数量恰到好处。少于这一数量,应用程序就无法对所有内容进行分类,也就无法为导航提供便利。再多的话,用户就会迷失方向,找不到自己的位置。*

*中心

中枢是应用程序的入口点,是整个应用程序的总览。当然,hub 不能显示应用程序中的所有内容,但它可以显示每个部分中足以引起用户兴趣的部分。例如,一个购物应用程序不会显示一个类别中的所有产品,但可能会显示前几个特色产品,并邀请用户查看更多。

部分

如果用户选择一个 hub 部分的标题,他们将被带到部分页面。区段页面负责传递有关该区段的任何一般信息,并为用户提供对该区段下所有单个项目或实体的访问权限。再次使用陈词滥调的产品和类别示例,工具部分将负责让用户使用所有可用的工具。这并不意味着所有的工具都会立即出现在页面上。通常过滤和排序功能使用户的生活更容易。

详述

当用户到达应用程序中的某个实体后,比如某个特定的产品,他们会被带到详细页面。详细页面负责显示关于该特定实体的所有信息。一个详细页面可能包含一张照片、一个描述、一些相关的实体、一个类别列表,或者谁知道还有什么。底线是细节页面是通知用户关于一个实体的专用地方。

9781430249832_Fig01-05.jpg

图 1-5。三层导航模型的图表,显示了中心层、部分层和细节层

平面导航

内容驱动的应用在三层导航结构中运行良好,但是有些应用并没有真正的内容结构。一些应用程序只是相似视图的集合——彼此都是对等的。Internet Explorer 是一个很好的例子,它遵循平面导航模式,因为会话中的浏览器实例彼此之间没有层次关系。

在实现平面导航的应用程序中,上面的应用程序栏(通常用于导航)提供对这些对等页面的访问,如图 1-6 所示。

9781430249832_Fig01-06.jpg

图 1-6 。平面导航模型的示意图

互动

将 chrome 添加到页面的第二个常见原因是为了交互。交互就像按钮一样,给用户一个与应用程序互动的机会。

让你的用户有机会与你的应用程序交互当然是一个好主意,但是设计界面上的传统控件不一定是提供这种交互的最佳方式。在设计界面上塞满用户可能需要或可能不需要的控件,对于让用户沉浸其中来说是次要的,同时仍然给他们机会在需要的时候调用一些交互。

屏幕上的内容通常不言自明,用户会很快知道或学会如何与之交互。一个用户(甚至是一个小孩)通常能够凭直觉感觉到触摸一些内容会给你带来更多的信息。同样,你不需要重复其他命令来影响屏幕上的内容,而是可以允许用户选择一个或多个项目,然后从应用程序栏中选择一个命令。在应用程序栏中放置命令可以让用户控制,因为应用程序栏根本不会占用任何空间,直到用户选择这样做。

我们希望设计我们的 Windows 8 应用程序,以便内容可以自己命令。通常,这仅仅意味着内容是可点击的。你可以在图 1-7 中看到内容命令自身的例子。

9781430249832_Fig01-07.jpg

图 1-7 。通常不需要额外的命令按钮来查看内容项的更多信息。最好让用户直接与内容互动

有时命令不能直接由内容来表示,在这种情况下,我们被建议利用边缘。这意味着一些原本会使我们的设计界面变得混乱的命令可以被放到系统级的 Charms 栏中,或者放到更低或更高的 app 栏中。这被称为利用边缘,因为这些条准确地“隐藏”在屏幕边缘,直到用户调用它们。在这里,我们再次将用户置于控制之下。

图 1-8 显示了一个应用程序,其应用程序栏可见。这个应用程序栏由用户从屏幕外通过滑动手势、通过右击鼠标或者通过按键盘上的 WIN + Z 来调用。该栏是属于应用程序的命令的主页。更具体地说,它是您放置影响用户当前在上下文中的视图的命令的地方。

9781430249832_Fig01-08.jpg

图 1-8 。应用程序栏随时准备为用户提供应用程序级别的命令,但是直到用户真正请求它时它才出现

图 1-9 显示了一个带有可见魅力栏的应用程序。该条由用户通过从屏幕右下滑动手势、用鼠标点击屏幕的右上角或右下角、或者按键盘上的 WIN + C 来调用。作为开发人员,我们实际上并没有改变 Charms 栏。它被窗户烤焦了。然而,我们能够在我们的应用程序中实现某些代码契约,因此我们的应用程序将响应用户激活的魅力。例如,我们的应用程序可以共享、搜索、共享到设备,并提供应用程序设置。

9781430249832_Fig01-09.jpg

图 1-9 。Charms 栏以可预测的方式为每个应用程序带来系统级命令

应用程序栏上的命令是特定于给定应用程序的,它们位于一致的位置很好,因为曾经使用过 Windows 8 的用户会确切知道在哪里可以找到它们。用户将很快习惯搜索和分享的工作流程,并乐于在每个应用程序中使用相同的工作流程。

请记住,如果一个命令是基本工作流的一部分,那么它不应该对用户隐藏,而是应该放在设计图面上。秒表应用程序的开始和停止按钮就是一个很好的例子。隐藏这些按钮毫无意义,事实上,可以说这些命令本身就是应用程序的内容。

布局

最后,应用程序被仅仅用来分离内容的 chrome 弄得杂乱不堪。我们在谈论线条、盒子和隔断。实际上,在大多数情况下,当导航和交互 chrome 消失时,布局 chrome 往往会消失,因为布局 chrome 经常将内容与导航或内容与交互分开,而不是内容与内容分开。

因为我们将整个屏幕作为应用程序的画布,而不是画线和框,我们可以将空间花在空间上——如图 1-10 所示的空白空间。在 Windows 8 中,我们不怕在事物之间留出喘息的空间。

9781430249832_Fig01-10.jpg

图 1-10 。Windows 8 不怕使用大量空间作为您内容的呼吸空间

我们也创造良好的布局与良好的排版。Windows 8 的字体设计有其意义和目的。标准字体和标准字体大小给了我们一个类型的斜坡,用于表示屏幕上元素之间的层次关系,并根据它们的角色或重要性自然地将它们分开,如图图 1-11 所示。

9781430249832_Fig01-11.jpg

图 1-11 。类型渐变传达了类型的重要性和层次

你的应用也应该实现所谓的 Windows 8 设计轮廓。设计轮廓是标准的页边距、页眉位置、内容填充、字体和字号,给用户一种强烈的亲切感,如图图 1-12 所示。这种一致性应该与独特的设计风格相结合,让你的应用程序不仅熟悉,而且有自己的个性。

9781430249832_Fig01-12.jpg

图 1-12 。标准的页边距和页眉位置为 Windows 8 用户提供了一定的一致性

快速流畅

Windows 8 应用应该始终以快速流畅的方式运行。一个快速流畅的应用程序反应迅速,流畅,使用有目的的动画和清晰的图形。

出色的用户体验的一部分是用户感觉他们是在直接与信息交互,而不是与传递信息的系统交互。触摸内容并实时拖动它是一种很好的用户体验,但前提是内容精确地跟随用户的手指,而不是抖动、滞后或落后。

在很大程度上,你创建的 Windows 8 应用会很快很流畅,即使你没有想到这一点。这是因为许多内置控件和函数在设计时都考虑到了这一点,也是因为 Windows API(Windows 运行时或 WinRT)只为任何可能需要太长时间(在这种情况下,太长时间被定义为 50 毫秒)的方法提供异步调用。

然而,有时候,作为开发人员,您将直接负责在屏幕上移动并与用户交互的元素的性能。无论何时出现这种情况,你都应该确保性能被认为是快速和流畅的

动画也有助于让用户感觉他在和一个有机系统互动。我们将在第六章更深入地讨论动画。

完美地捕捉和缩放

Windows 8 不受限于固定硬件。有数百种电脑型号和许多外形规格将乐于运行 Windows 8 和您的应用程序。因此,你的应用程序应该具有适应性,你应该有意识地考虑每个页面在每个可能的视图状态下的外观。

您将处理的典型 Windows 8 视图状态包括:

  • 全屏横向:整个屏幕,宽度大于高度
  • 全屏纵向:整个屏幕,其高度大于宽度
  • 抓拍:只是左边(或右边),是 320 像素的风景
  • 填充:当另一个应用程序被抓取时剩余的空间

您不必支持纵向视图,但必须支持快照和填充视图。无论你喜不喜欢,你的用户都可以抓拍你的应用或者你旁边的应用。即使你的应用没有刻意处理这些状态就通过了认证,当你的用户发现的时候也会很尴尬。

使用正确的合同

我们在电脑上安装操作系统的一个主要原因是,抽象出我们希望以一致的方式工作的所有琐碎任务,而不必为每个应用程序重新创建它们。打印机驱动程序过去并不存在,因此每个应用程序都必须被编程,以便与任何可能正在使用的打印机对话。对这项任务来说,艰巨是一个合适的词。

一个可能成为抽象概念的现代规范是社交网络,或者更普遍的说法是分享。Windows 8 从我们的应用程序中抽象出了分享的概念,并将其包装在一个所谓的合同中,作为开发人员,您可以实现该合同。如果你不熟悉的话,契约只是你的代码中遵循的一种模式,当它试图要求你的应用程序共享或搜索或其他内容时,它会满足 Windows 期望找到的内容。在代码中实现契约并不是一件困难的事情。这样做的巨大优势是,只要你的应用程序能够共享并正确实现契约,那么它突然就能够与参与同一契约的每个应用程序共享。它甚至能够与应用程序共享,而这些应用程序是在你将自己的应用程序放入商店后才出现的!

搜索是另一种流行且常用的契约。通过正确的契约实现(同样是一个相当简单的任务),用户甚至可以在启动应用之前搜索你的应用,你可以决定当你的应用被搜索时会发生什么,以及如何产生搜索结果。

有很多 Windows 8 合同,我建议将任何可以增加实际价值的合同添加到您的应用程序中。

投资一块大瓷砖

实时互动程序是用新信息或图像更新的开始屏幕互动程序。动态磁贴很有效,因为它们是信息性的。我发现自己有时只需快速浏览一下我的开始屏幕,就能得到我需要的所有信息。我可以看到当天的天气,我的下一个约会,以及头条新闻,而不用启动任何应用程序。

请记住,应用程序的磁贴不仅会通知用户,还会邀请他们进入你的应用程序。您希望您的用户使用您的应用程序并经常使用它,您可以通过投资于您的实时磁贴的质量和功能来促进这种使用。

没有理由不投入创建丰富的磁贴支持所需的微小时间。制作一个宽版本的磁贴非常好,可以让用户在开始屏幕上更突出你的应用。如果您制作宽切片,建议您为其提供实时切片功能。什么都不做的双宽有点让人失望。

感受联系和活力

Windows 8 应用程序的设计目标之一应该是帮助用户感觉不像是在与设备交互,而更像是在直接与信息交互。

到目前为止,我们谈论的许多原则都有助于实现这一点,但是让用户保持联系并让他们的信息充满活力的一个特别重要的方法是通过屏幕通知和音频提示来真正打断他们正在做的事情。毕竟,实时磁贴是信息丰富的,但是用户更多的时间将花在应用程序上,而不是盯着他们的开始屏幕。对于用户认为重要的通知,无论他们当时正在做什么,他们都希望被打断。

当用户收到电话或即时消息时,当他们在网上拍卖中出价被超过时,当然还有当他们的彩票被抽出时,通过通知他们,让用户感觉他们的设备是活的。

漫游到云端

漫游到云是一个朗朗上口的现代术语,简单地说就是我们将某些信息保存到互联网托管的位置,而不是保存到设备上。这样,当用户在他的设备上重新加载操作系统或登录到另一个设备时,他们过去选择的设置和首选项可以无缝地使用。

在 Windows 8 中漫游的伟大之处在于它对开发者来说极其简单。所有需要做的就是通过 Windows 提供的漫游存储 API 保存设置。该设置实际上存储在本地,但 Windows 负责将所有这些设置与用户的 Microsoft 帐户同步(而不是与他们的 SkyDrive 同步)。清单 1-1 显示了一个保存到漫游存储器的示例设置,只是为了向您展示它有多简单。

清单 1-1。 用户最喜欢的颜色被保存到漫游设置中,因此它将在任何设备上可用

//JavaScript snippet
var appData = Windows.Storage.ApplicationData.current;
appData.roamingSettings.values["favoriteColor"] = "blue";

不仅要考虑漫游用户的数据,还要考虑他们的任务。如果用户正在做某事,当他们在另一台计算机上继续时,帮助他们重新开始。如果你已经使用了 Windows 应用商店中的网飞应用,你可能会注意到它会保存代表你在观看的电影中所处位置的时间戳,并在你返回时恢复它,即使你返回到不同的设备。用户喜欢这样,你应该在你自己的应用程序中寻找这个原则的应用。

遵循设计原则

我们已经看到了设计良好的 Windows 8 应用程序的许多特征,我们还有一个特征。最后一个特点是,应用程序应该遵循 Windows 设计原则。接下来我会列举并解释设计原则。这些原则比我们一直在看的特征稍微不实用,似乎更深奥,但我要提醒你不要忽视它们。理解并遵循这些一般原则将指导你设计你的应用程序,即使你不是从一个项目模板开始。

微软设计原则

http://msdn.microsoft.com/en-us/library/windows/apps/hh464920.aspx#traits_8_embrace_metro的 MSDN 上,Windows 8 的设计原则得到了完整的记录和更广泛的解释。它们是简单、高层次的指导原则。这些是 Windows 8 应用程序应该尊重的价值观,目的是让应用程序做好自己的工作,让用户开心。

根据微软的说法,这些原则是:

  • 对工艺表现出自豪
  • 少花钱多办事
  • 快速流畅
  • 真正数字化
  • 团结一致赢得胜利

展现对工艺的自豪感

一个应用程序设计者/开发者应该对工艺表现出自豪的原则当然说明了这些原则是多么的普遍。这意味着你永远不应该避免花费额外的时间来获得正确的细节。你应该担心的只是动画的行为和颜色的匹配。您应该关注左边距的确切大小以及用户在边缘情况下的体验。

让我用一个我不幸经常碰到的例子来说明这个原则。告诉我你是否能看出图 1-13 中的视图有什么问题。

9781430249832_Fig01-13.jpg

图 1-13 。典型的网格布局,但有一个微妙的设计缺陷

我希望你注意到了最左边的列表条目几乎是对齐的,但并不完全对齐。即使你的用户没有有意识地注意到一些看起来如此琐碎的事情,他们也会下意识地注意到它,这将是一个贬损者。

事半功倍

用更少的资源做更多的事情意味着你打破了现代的轨迹,在屏幕上添加了太多的东西,以至于没有一个东西达到它的目的。

当你设计用户将遵循的使用流程时,要记住的词是本质。问问你自己,你是否在展示信息的本质并给用户本质命令。不必要的信息和命令不仅是多余的,更糟糕的是会分散注意力。

请记住,就像 Windows 本身一样,您并不试图最终被发现。最终身临其境要好得多。

快速流畅

这个原则听起来很熟悉,因为它是设计特征的重复,这说明了这个概念的重要性。当用户使用一个他会描述为“快速和流畅”的应用程序时,他的感觉是很难描述的,但当你看到它时你就知道了。

不要害怕花一些钱在专业的设计帮助上,这些帮助不仅在静态图形方面有经验,而且在动态屏幕和用户体验方面也有经验。

真正数字化

我相信在应用程序开发中,哲学比科学更重要。如果你缩小过去 30 年,看看计算的大规模采用,很明显开发者仍然在试图找出好的架构和可用性。

我们抓住我们知道的范例,把它们拖进我们的数字系统,同时对它们的不适合做鬼脸。也许只有现在我们才知道,数字系统有自己的规则,而且这些规则往往比我们模拟世界的规则更自由,用户可以学习甚至热爱数字世界。

在我们开发应用时,我们充分利用我们拥有的数字系统,避免应用设计接受与数字世界无关的模拟世界的约束。毕竟,我们是在和屏幕上的像素打交道——这是一个必须接受的基本事实。

众志成城

用户不使用 apps他们完成任务。有时,这些任务涉及单个应用程序,但通常它们涉及应用程序的编排。想象一下下面的场景。

你的应用程序可以帮助用户在餐厅预订。你的用户可能会单独使用你的应用,但更有可能你的用户会:

  • 在机场登上自动扶梯
  • 查看他们的旅行管理应用程序,找到他们酒店的位置
  • 查看酒店附近的餐馆
  • 根据用户评论选择餐馆
  • 在餐厅预订(使用您的应用程序!)
  • 将预订确认发送给同事,然后走下自动扶梯

那个用户是一个快乐的用户。他不仅仅使用了一个应用程序;他在很短的时间内完成了一些重要的事情。在乘坐自动扶梯的过程中,免费的和信息丰富的动画非常重要,每个应用程序的 UX 都非常重要,应用程序到应用程序的共享也非常重要。

要制作一个成功的 Windows 8 应用,你必须考虑用户。其中一部分是确保你的应用程序能够与其他应用程序和设备很好地配合,以完成整个使用场景。

这个设计原则的另一个方面是利用已建立的约定、标准和建议。通过这样做,你将利用用户已经了解的 Windows 8 应用。他们会在你的应用中感到安全和熟悉。

我们已经看到了一些设计特点和原则,希望能在你设计应用程序的过程中有所帮助。现在让我们来看看一个虚构的应用程序设计。

设计场景

在我看来,衡量一个成功应用的标准只有一个。不是安装数量的问题。不是发射次数的问题。不是很高的收视率或很好的评论,甚至不是你银行账户里的钱。

衡量一款成功应用的标准是它给用户生活带来的价值。

永远不要忘记这一点。如果你开发了一个能带来价值的应用,你就开发了一个能带来金钱的应用。不幸的是,我们不能直接量化附加值,所以我相信我们会继续根据许多其他因素来衡量我们的应用程序,我相信你会继续欣赏积极的现金流。

范围

在应用程序开发中获胜的最好方法之一就是做好定义你的应用程序的范围 的工作。你的 app 要做一件事,并且做好。我们称之为你的应用程序的最擅长的“陈述

你可能注意到了当今软件世界的趋势,尤其是在移动领域,从几个无所不能的应用转向许多每个都做得很好的应用。如果你的应用程序还能帮他们报税和煮咖啡,你就不会让任何人心碎。如果它做了它想做的事情,并且做得很好,你的用户会喜欢它,给它很好的评价,并给你送现金。

做好一件事意味着很好地界定你的应用。这意味着在你写任何代码之前,你要确定你的应用程序会做什么不会做什么。你可能已经知道,确定它不能做什么——对功能说——比添加新功能更困难。

明确地说,巨大的、健壮的和功能齐全的应用程序有它们的位置,如果你有办法承担这些,那就让它成为你的范围。然而,如果你是个人开发者,那么你需要练习裁剪特性。仅仅因为你实现某事,仅仅因为它真的很酷并不意味着你应该去做。作为开发人员,我们倾向于成为理想主义者,我们倾向于非常想添加一些特性来证明我们可以做到。

为了保持特性的统治地位,我推荐使用一个最擅长的语句。你最擅长的陈述是一个简单、简洁的句子,通过填写下面句子中的空格形成:

这款应用在 _______________ 是同类产品中最好的。

确保你的回答具体、简洁、清晰。这里有一个例子:

这款应用是同类应用中最好的,它帮助用户寻找当地志愿者的机会,帮助老年人或残疾人做家务、庭院工作或其他家务。

请注意,该声明是如何具体说明谁参与其中的——志愿者加上老年人和残疾人。声明也简短明了。该应用程序不会组织志愿者活动或帮助筹集资金,也不会接受非营利组织的捐款。它只会帮助用户找到一个志愿者的机会。

这句话通过清楚地陈述它做什么和排除它不会做什么,对定义你的应用程序的范围有很大的帮助。然而,帮助人们找到志愿者的机会可能涉及不止一个使用场景。

使用场景

我们的应用程序的愿景正在形成,但它仍然是抽象的,所以为了巩固它,我们将确定使用场景是什么。对于这个应用程序,以下内容如何:

  • 允许用户浏览当前位置附近和不久的将来(可能是接下来的两周)潜在的志愿者机会,并按位置和日期过滤机会。
  • 允许用户查看他们所有的当前志愿者机会
  • 允许用户与其他志愿者和接受帮助的人交流。

当你头脑风暴的时候,你可能会产生很多场景,但是这个列表应该被精简,只包括那些直接支持最佳陈述的场景。

这些使用场景中的每一个都暗示了许多支持特性或功能。例如,提供潜在的志愿者机会意味着我们向用户提供每个机会的完整细节,包括位置和持续时间,可能需要什么工具等等。通常,这些使用场景会形成我们将在 hub 页面上看到的部分。

在这一点上,有一些图表纸甚至一些专门的应用程序设计纸将想法写在纸上是非常有帮助的,而不会有实际实现的阻碍。我已经创建了一个 Windows 8 应用设计表,并在http://codefoster.com/designsheet以 PDF 格式提供。第一页包括为应用程序设计标准三层导航模型的框架,第二页只是一个 1366 x 768 的整页设计图面,带有浅色网格以及推荐边距、快照视图和应用程序栏的指南。希望这个资源可以帮助你设计你的应用。

9781430249832_Fig01-14.jpg

图 1-14。来自codefoster.com/设计表的 Windows 8 应用设计表

让我们使用这个设计表来勾画出一个枢纽网页。我们将我们的应用程序命名为好帮手,我们将有三个部分:我的演唱会连接附近的演唱会。这些部分直接对应于我们的三个使用场景。

请注意,该应用程序确实遵循了基本的 Windows 8 设计准则,但我们在布局上有点创意(可能还不够),让我们的应用程序有一些自己的个性。在我的演出部分和附近的演出部分中的机会都使用相对较大的矩形,以允许我们在必要时将一些图像和大量信息带到中心页面。连接部分提供了一列较小的矩形,类似于聊天会话,因为该部分有助于应用程序成员之间的通信。

请记住,hub 页面应该作为整个应用程序范围的一瞥,因此我们应该为每个使用场景找到一个位置。用户喜欢在应用程序中有方向感,一个设计良好的 hub 可以通过不断向用户提供概览来实现这一点,并使其易于深入了解关于给定部分或实体的更多信息。

很明显,hub 页面上没有足够的空间来放置应用程序中所有可用的内容。例如,nearly gigs部分可能有 400 个机会,但 hub 只会显示其中的一部分。在这种情况下,将最近的机会带到用户中心是有意义的,因为这些机会可能是他最有可能注册的。

该中心让我们不仅可以访问应用程序中可用的部分,还可以直接访问某些项目。在图 1-15 中的概念图中,有三个项目填充了我的工作部分,表明用户已经注册了这三个志愿者机会。触摸其中一个项目,用户将直接导航到该机会的详细信息。

9781430249832_Fig01-15.jpg

图 1-15 。Good Help 应用程序中心页面的第一张草图

让我们继续我们的应用程序的设计,并绘制一个页面的概念。我们将设计 gig 页面,它将传递任何一个 gig 的完整细节。这是用户通过触摸中心上的一个机会来导航到的页面。图 1-16 显示了这个概念。

9781430249832_Fig01-16.jpg

图 1-16 。详细页面的草图

这个设计场景就是这样。我希望这个明显虚构的应用程序在概念上足够接近您正在开发的应用程序,以便您能够快速应用这里的设计原则。

摘要

在这一章中,我们探讨了一个设计良好的 Windows 8 应用程序的一些特征,以及一些需要牢记的设计原则,以帮助指导您完成应用程序的设计和实现过程。

我们访问的最重要的设计特点鼓励我们使用微软的设计风格,包括让用户沉浸在他们的内容中,尽我们所能消除干扰。Windows 8 应用更注重内容的沉浸感和一致性,而不是可发现性。

应用程序开发人员必须打破为 chrome 使用设计界面的习惯,这可能是静态导航、用户交互或显式布局。相反,我们学习在不转移用户注意力的情况下替换这种功能的技术。例如,我们通过让内容执行自己的命令来学习如何导航。我们学习了如何让用户通过利用屏幕边缘进行交互——使用应用程序栏和魅力栏。最后,我们学习了如何通过有意识地使用空间和排版来布局我们的内容,而不需要显式的布局工件。

我们通过运行部分设计场景得出结论,在该场景中,我们处理应用程序的范围,然后粗略定义其中心页面和一个详细页面。这个练习与你创建的每个应用程序的过程大致相同(尽管规模较小)。

设计过程是伟大的,当然也是关键和先决条件,但现在是时候让我们动手,投入代码,并学习创建一个实际的 Windows 8 应用程序的基础知识了。*

二、Windows 8 开发简介

image 注意对于软件开发人员来说,这是一个激动人心的时刻。

这本书的目标是帮助你深入了解 CSS,尤其是当你为 Windows 8 开发应用程序时它的应用方式。然而,如果你没有任何开发 Windows 8 应用程序的经验,你将很难实践你所学的任何东西。因此,如果这对你来说是一个全新的世界,我们将利用这一章来了解 Windows 8 架构、对你开发应用有价值的工具,以及如何在本地和 Windows 应用商店分发你的应用。

Windows 8 架构

在 Windows 8 进入我们的生活之前,Windows 应用程序可以使用 C++编写,并且可以本地访问 Windows 核心 Win32 库。他们可能更愿意坐得高一点(逻辑上),用 C#或 Visual Basic 编写,在。NET 框架。或者,如果你稍微扩展一下你的思维,想象一个 web 应用程序是一个 Windows 应用程序,那么一个应用程序可以使用 web 语言编写,托管在一个 web 服务器上(无论是本地的还是远程的),然后甚至位于 web 浏览器的更高位置。

Windows 8 并没有抛弃任何现有的应用程序创建模式,但它确实引入了一种全新的、令人兴奋的模式。

Windows 8 引入 WinRT。WinRT 是一个全新的现代 API,是为现代应用程序而从头设计和构建的。它不仅仅是 Win32 库或。NET 框架。

Window 的新架构令人兴奋的原因之一是,它可以被几种不同的技术堆栈所瞄准。它可以被 C++和 XAML、C++和 DirectX、C#/VB 和 XAML 以及 JavaScript 和 HTML 作为目标。不同的语言被投射到 WinRT 域中,所以它们不构成额外的层次,并且该模型为将来将其他语言投射到 WinRT 中留下了可能性。图 2-1 显示了目前 WinRT 上的不同的语言堆栈。

9781430249832_Fig02-01.jpg

图 2-1 。可以针对 WinRT 的语言的宏观视图

这些堆栈中的每一个都有其独特的环境和优势。如果你用 C++创作,你可以使用一些现有的 C 和 C++组件。如果你是 C#/VB 和 XAML 的作者,你会对。NET 框架。它不是整个框架,但它是为这些现代应用程序量身定制的子集。

如果您使用 JavaScript 和 HTML 进行创作,您将获得广泛的、基于标准的 web 堆栈,供全球大量开发人员使用。你得到了浏览器的文档对象模型,你得到了我们非常喜欢但又不太喜欢的动态持久语言——JavaScript。也许您得到的最令人兴奋的东西是已经编写了数量惊人的 JavaScript 代码来做许多您可能想做的事情。

然而,当你使用 web stack 为 Windows 8 开发一个应用程序时,该应用程序并不在针对 web 服务器的浏览器中运行;它在平台上本地运行。该应用程序是硬件加速的,并由系统信任以访问系统本身和所有连接的硬件。这对开发者来说是一个全新的空间。

除了直接访问底层 WinRT 之外,Windows 8 开发人员还可以获得 Windows JavaScript 库(WinJS)的额外帮助。WinJS

WinJS 提供了一些 JavaScript 和一些 CSS 样式。稍后,我们将更深入地研究 WinJS 提供的 CSS 样式。

当我们开始编写应用程序时,我们需要一些好的工具,幸运的是,微软提供的工具是首屈一指的。接下来我们将对此进行研究。

工具

微软的旗舰开发工具是 Visual Studio。它已经存在了足够长的时间,在设计和功能上经历了一些重大的演变。除了 Visual Studio,开发人员也可以使用 Blend。

Visual Studio 2012

Visual Studio 2012 (VS2012)是最新的版本,这一版本的设计中没有遗漏任何改进!VS2012 在许多方面与它的前辈几乎没有相似之处,但它没有失去任何功能。您仍然可以创作许多不同的项目类型,现在也可以创作 Windows 8 应用程序。

VS2012 产品之一——Express——只针对 Windows 8 应用,完全免费。当然,它不具备高端付费产品的所有功能,但它仍将从头到尾管理你的应用。这对于学生开发者来说尤其令人兴奋,因为他们没有大的开发机会,也没有钱购买开发工具。

如果你想开发一个 Windows 8 的应用,你必须有 Windows 8,你必须有 Visual Studio 2012。早期版本的 Windows 将运行 VS2012,但无法创建 Windows 8 应用。

项目模板

面向 Windows 8 项目的 VS2012 项目模板将让您快速上手。这些基本模板中的任何一个都将引导你开始使用我们将在本书中学习的 CSS,所以不要觉得你已经走了很远。

让我们从简单的模板开始,然后逐步完善。从以下每个模板创建新项目,然后按照我指出的构成项目的各个页面的结构进行操作。

空白模板

空白模板的稀疏内容不会让您感到惊讶。毕竟,它应该是空白的。然而,如果你是那种对空白模板产生的少量明显的魔力感到好奇的人,你可以访问我的博客文章http://codefoster.com/Windows-8-Building-Up-to-Blank,阅读更多关于这个简单模板的内容。

要创建新的空白项目:

  1. 在运行 Windows 8 的计算机上启动 Visual Studio 2012

  2. Click File | New Project

    image 注意如果你使用的是 Visual Studio 的专业版,你会看到一个类似于图 2-2 的屏幕。如果你使用 Visual Studio 速成版,那么你的选择会更少,但概念仍然存在。

    9781430249832_Fig02-02.jpg

    图 2-2 。“新建项目”窗口为您提供了几个项目类型选项

  3. 从左侧窗格中选择“JavaScript”|“Windows 应用商店”,然后从模板列表中选择“空白应用”。确保您对项目的位置和名称满意,然后单击“确定”。

几秒钟后,你就可以运行一个成熟的 Windows 8 应用了。你可以点击工具栏上的绿色箭头在本地运行这个应用程序,但是结果并不令人兴奋。图 2-3 显示了当你运行一个从空白模板创建的项目时的样子。

9781430249832_Fig02-03.jpg

图 2-3 。从空白模板创建的项目的第一次运行。你几乎看不清的白色文字写着“内容在此处”,并作为占位符供你添加内容

让我们看一下为我们创建的项目,确保我们对所涉及的文件有一个坚实的理解。

如果您有任何使用网站的经验,您可能会注意到解决方案资源管理器中的文件在许多方面类似于 web 项目。像 web 项目一样,有像jsimagescss这样的文件夹,像 web 项目一样,在根级别有一个default.html文件。您可以深入到所有级别,亲自查看我们没有处理太多的文件。当你试图获得核心概念时,有一个简单的开始是很好的。

在我们查看所涉及的 HTML、CSS 和 JavaScript 文件之前,让我们先来看一个您可能不熟悉的文件— package.appxmanifest。这个文件包含了你的 Windows 8 应用的所有元信息。当应用提交到 Windows 应用商店时,这是描述应用的重要信息。

package.appxmanifest文件(也称为清单)只是一个简单的 XML 文件,但您很少需要直接盯着 XML,因为双击清单时 Visual Studio 启动的 GUI 设计器相当不错。

现在我们来看 HTML 文件。双击default.html打开它,或者如果你面前没有你的项目,就看一下清单 2-1 。

***清单 2-1 。***伴随一个新的空白项目的 default.html 文件

1<!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta charset="utf-8" />
 5     <title>NewBlankApp</title>
 6
 7     <!-- WinJS references -->
 8     <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
 9     <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
10     <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
11
12     <!-- NewBlankApp references -->
13     <link href="/css/default.css" rel="stylesheet" />
14     <script src="/js/default.js"></script>
15 </head>
16 <body>
17     <p>Content goes here</p>
18 </body>
18 </html>

我想强调的是,这个文件中完全没有任何专有的东西。如果你看过 HTML5,你会认出简洁的DOCTYPE指令,带有脚本和样式表链接的基本head部分,以及世界上最简单的内容体“内容在这里”。

第 13 行和第 14 行引用的脚本和样式表文件以正斜杠(/)开始,因此从项目的根开始,继续引用来自css文件夹的default.css文件和来自js文件夹的default.js。您将逐渐习惯这种约定,因为所有内置的模板文件都被分成了共享一个名称的.html.css.js文件。

清单 2-1 的第 8-10 行乍一看可能很奇怪,但是我会解释为什么这些都是由完全标准的 HTML5 标记组成的。统一资源标识符(URI),比如第 8–10 行的linkscript元素所包含的,以一个 scheme(比如 http)开始,然后是一个冒号(:)。冒号后的所有内容都由 scheme 定义。

对于流行的 http 方案,URI 的剩余部分被定义为http://{hostname}/{path},其中hostname通常是服务器的名称或 IP 地址,path是被请求文件的完整路径。

然而,清单 2-1 中的 URI 省略了这个方案,规则是如果 URI 的一个段被省略,那么它默认为当前请求的相同段的值。对于网站来说,默认请求通常是 times http,但 Windows 8 应用的方案是ms-appx。所以第 8-10 行可以写成类似于清单 2-2 的形式。

***清单 2-2 。***ms-appx 方案是 Windows 8 应用的默认方案

<link href="ms-appx: //Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
 9  <script src="ms-appx: //Microsoft.WinJS.1.0/js/base.js"></script>
10   <script src="ms-appx: //Microsoft.WinJS.1.0/js/ui.js"></script>

ms-appx方案中,双斜杠后面的 URI 段是代码所在的包。在图 2-4 中可以看到,ui-dark.css文件(来自清单 2-2 的第 8 行)存在于项目引用下的Windows Library for JavaScript 1.0中,该引用包的包名为Microsoft.WinJS.1.0

9781430249832_Fig02-04.jpg

图 2-4 。ui-dark.css 文件位于被引用的包中

只要请求正在使用ms-appx方案,系统就知道它们是安全的请求,并且这些请求被认为是在本地上下文中。另一方面,对http方案的请求不被认为是安全的,Windows 8 在所谓的网络环境中运行它们。你可以通过访问http://aka.ms/win8contexts找到更多的信息。

好了,HTML 文件中没有什么神奇的事情发生,所以我要继续向你保证 CSS 或 JavaScript 文件中也没有发生。

空白模板的 CSS 文件位于css文件夹中,名为default.css。文件中没有功能代码,但是包含了一点框架来帮助您入门。清单 2-3 向您展示了在default.css的默认实例中您会发现什么。

清单 2-3 。 空白项目模板附带的 default.css 文件

body {
}

@media screen and (-ms-view-state: fullscreen-landscape) {
}

@media screen and (-ms-view-state: filled) {
}

@media screen and (-ms-view-state: snapped) {
}

@media screen and (-ms-view-state: fullscreen-portrait) {
}

这些都只是没有任何效果的样式规则和媒体查询的空壳。然而,这是你的空白画布。当第三章开始向你展示如何定义样式规则时,这就是它们要去的地方。

我们要看的最后一页是 JavaScript。default.js文件在清单 2-4 中,正如你所看到的,它比 HTML 和 CSS 文件要长。

清单 2-4 。空白项目模板中包含的 default.js 文件

// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509
(function () {
    "use strict";

    WinJS.Binding.optimizeBindingReferences = true;

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !==
                activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    app.start();
})();

我不会花时间解释这个文件中发生的所有事情,但是我想指出几件事情。

首先,您应该知道这整个文件是标准的 JavaScript——从技术上讲是 ECMAScript 5。

其次,流程生命周期管理(PLM)在这里处理。PLM 是您编写的代码,用于确保您的应用程序在启动、暂停、重新激活和终止时表现良好。如果你写对了代码,你的用户对你的应用的体验将会是快速和无缝的。

最后,注意 JavaScript 文件中的所有代码都包装在所谓的立即函数中,如清单 2-5 所示。

清单 2-5 。 一个立即函数包装代码,就像一个命名空间,并保持它与其他模块和全局命名空间隔离

(function () {

    ...

})();

这个立即函数定义一个函数,然后立即运行它。起初,这似乎是一件非常奇怪的事情。为什么需要定义一个函数并立即调用它?你就不能写代码让它执行吗?是的,你可以。immediate 函数是 JavaScript 中的一个常见技巧,它利用了 JavaScript 的函数作用域。功能就像拉斯维加斯。函数中发生的事情留在函数中。因此,你可以在即时函数中任意使用变量和函数定义,而不会添加一堆应用程序其他部分可以看到的垃圾,这些垃圾肯定会造成混乱和冲突。

记住,我们只是触及 JavaScript,因为这毕竟是一本关于 CSS 的书。不过,还有一件事我希望你至少能够认识到,那就是一个事件

事件在许多现代编程语言中都很流行。事件是当某件事情发生时触发的方法。如果用户单击一个按钮,就会触发一个事件。如果用户在屏幕上滚动某些东西,应该会触发一个事件(即使他们只滚动了一个像素)。

我们编写的 JavaScript 应该响应事件,为了做到这一点,我们需要定义方法并将它们绑定到正确的事件。我举一个很基本的例子。

让我们在用户点击按钮时显示一个对话框。为此,我们可以使用清单 2-6 中的代码。

清单 2-6 。 一个简单的事件处理程序,通过点击按钮来启动一个消息框

document.getElementById("myButton").onclick = function(e) {
    Windows.UI.Popups.MessageDialog("Hello").showAsync();
};

现在,让我们把这段代码拆开来理解到底发生了什么,以及事件处理程序是如何工作的。

第一部分说document.getElementById("myButton")只是引用了一个在 HTML 中定义的 id 为myButtonbutton

.onclick是该按钮的点击事件。它的值最初是null,但是它希望我们提供一个函数,当按钮被点击时调用这个函数。

清单的其余部分是函数,它只是显示一个对话框,在用户每次单击按钮时显示“Hello”。

为什么选择空白项目?

如果您的应用程序只需要一个页面,空白项目是一个很好的起点。如果你正在开发一个游戏,游戏中的所有动作都发生在一个canvas元素中,那么就没有理由将用户导航到另一个页面。

如果您不喜欢有人为您编写代码,您也可以选择使用空白模板。如果你想从零开始(或者几乎从零开始),那么这里有另一个很好的理由。

关于空白项目模板,还有很多东西需要学习,但这只是一个概述,在深入了解之前,我们将继续学习其他项目模板。接下来,我们将了解导航项目模板。

导航模板

图 2-5 展示了一个用导航模板创建的应用程序。它看起来几乎和图 2-3 中的空白模板一样稀疏,但是它确实有一个页眉。不过,页眉并不是唯一的区别。

9781430249832_Fig02-05.jpg

图 2-5 。从导航模板创建的项目的第一次运行。我们仍然有白色的小文本,上面写着“内容在这里”,但是现在我们也有了页眉

导航项目模板在空白模板之外添加了一些东西,主要目的是为您提供从一个页面到另一个页面的导航框架。这种改进的导航实际上是由 WinJS 库提供的。我将向您展示所有的差异,并告诉您为什么这个导航框架对我们来说是一个好东西。

如果您要使用文件差异实用程序来查看空白项目模板和导航模板,您会看到两者之间的以下差异。在导航模板中:

  • default.css 中有一些基本的样式更改,提供了符合 Windows 8 设计原则的页眉。
  • default.html 文件不再包含主要内容(“内容放在这里”),而是包含一个名为 contenthost 的东西。
  • 项目中的 js 文件夹包含一个 navigator.js 文件,该文件定义了 contenthost 的行为方式。default.html 页面引用 navigator.js
  • 该项目有一个 pages 文件夹,其中有一个 home 文件夹,home 文件夹包含它自己的 HTML、CSS 和 JavaScript 文件。按照惯例,每个页面都将位于 pages 文件夹中自己的文件夹中。

这些几乎是所有的差异。不是很多。为什么这很有帮助?

你可能知道,在 HTML 中,你可以创建超链接,并轻松地从一个文件导航到另一个文件,但至少有几个原因可以解释为什么超链接对于 Windows 8 应用程序来说是不够的。

首先,超链接创建一个新的 HTTP GET 请求,并依赖 GET 请求中可用的查询字符串参数作为传递数据的唯一方式。另一方面,使用导航框架,我们可以在从一个页面导航到下一个页面的过程中传递健壮的 JavaScript 对象。

第二,超链接把用户从一个页面带到另一个页面,让前一个页面的所有范围和上下文完全消失。每个请求都是一个全新的上下文。这给开发人员带来了真正的痛苦,尽管 web 开发人员会发现这是一个常见的问题,但在现代的客户端应用程序中,这是不必要的。导航框架在应用程序的整个生命周期中让用户停留在default.html页面上,只是通过替换default.html的 DOM 中的内容来将用户导航到另一个页面。这种通用模式被称为单页面架构(SPA ),它越来越受欢迎,甚至在公共网页上也是如此。

图 2-6 展示了超链接导航,而图 2-7 展示了使用单页面架构改进的导航。

9781430249832_Fig02-06.jpg

图 2-6 。超链接到 page2.html 打破了用户的上下文创建一个新的上下文

9781430249832_Fig02-07.jpg

图 2-7 。通过 WinJS 库导航保持了上下文的完整性,使开发人员的工作更加轻松

为什么要选择导航项目?

对于任何可能实现多视图的应用程序来说,导航项目都是一个很好的起点。如果你的应用程序要向用户显示产品列表,然后允许他们选择一个产品来查看更多信息,那么你可能需要导航。

我几乎从导航模板开始每个项目,即使我知道我将实现一个网格。导航模板提供的导航功能非常有用,但编写起来很繁琐,但我喜欢从头开始创建网格。

网格模板

接下来是网格项目模板,如图图 2-8 所示。这个庞大的模板包含了大量的代码,如果不小心的话,你会被吓到的。仅网格项目模板就包含了将近 500 行 JavaScript 代码。大小的原因是,除了实现导航框架(我们在上一节中讨论过),它还定义了一堆样本数据,并包含三个独立的完整页面,实现良好的三层导航。

9781430249832_Fig02-08.jpg

图 2-8 。从网格模板创建的项目的第一次运行。我们看到的是为我们创建的三层导航模型的中心

网格模板实现了一个名为 *3 层导航的应用导航模型。*强烈建议 Windows 8 应用采用这种三层导航模式。遵循它会给你的用户带来一致性,而设计你自己的模型会有迷惑或失去他们的风险。使用这种导航模型有两个重要原因。首先,它背后有大量的用户研究,其次,它是用户已经熟悉的惯例。

网格模板的核心是 ListView。我们将在本书中深入探讨列表视图。现在,只需知道 ListView 是为您提供熟悉的实体网格的控件。这些实体以瓦片的形式出现是相当普遍的,但这当然是可选的。

为什么选择网格项目?

当您的应用程序类似于基本的三层导航模型时,网格项目可以让您快速从 0 到 60。这是一个很好的学习工具,我建议你使用这个模板创建一个应用程序,然后浏览并尝试对代码进行逆向工程。网格模板最大的一个优点就是已经实现了 Windows 8 的设计原则。边距宽度合适,字体大小合适,ListView 组之间的间距合适。

当您更加熟练地创建自己的 ListViews 并使用 CSS 实现设计原则时,我建议您放弃这个模板,使用导航模板。我觉得网格模板引入的复杂性超过了它的价值,但这只是我的看法。

我已经向您介绍了我认为最重要的三个项目模板。还有更多我没讲的。拆分项目模板有它的位置,但它适用于相对狭窄的一组应用程序。固定宽度的项目模板添加的实际代码非常少,如果我需要它的功能,我倾向于自己编写。

唐总管

如果您使用过任何主流浏览器的开发工具,那么您应该熟悉获取 HTML 文档的实时版本的概念。这种对象形式的实时文档被称为文档对象模型(DOM)

当您使用 Visual Studio 2012 在调试模式下运行 Windows 8 的 HTML/JavaScript 应用程序时,您会在 Visual Studio 中获得另一个名为 DOM Explorer 的窗格。如果您没有看到 DOM Explorer,那么请在 Windows | DOM Explorer 下的调试菜单中查找。

DOM Explorer 为当前运行的应用程序提供了 DOM 的分层表示。它有效地向您展示了 HTML 的外观,但包括了您的脚本(或 WinJS 脚本)在应用程序运行时可能进行的任何动态添加或修改。如果您使用 JavaScript 向 HTML 页面动态添加一个按钮,您将不会在 HTML 文件中看到该按钮,但是它会在 DOM Explorer 中显示。

DOM Explorer 对于开发和调试非常有帮助。图 2-9 显示了 DOM Explorer 的典型视图。

9781430249832_Fig02-09.jpg

图 2-9 。当你的应用程序运行在调试模式时,Visual Studio 中的 DOM Explorer 显示你的文档对象模型(DOM)的实时视图

在 DOM 浏览器的左侧(在图 2-10 中突出显示),你可以看到整个 DOM。如果你的应用程序中没有任何花哨的 JavaScript,那么这个 DOM 看起来就像你的default.html文件。

9781430249832_Fig02-10.jpg

图 2-10 。DOM 包括您编写的 HTML 以及运行时动态注入的任何东西

在图 2-9 中的 DOM 上方,注意选择元素按钮。当您单击该按钮时,您的应用程序将成为焦点(在 Visual Studio 前面),您有机会选择您可能感兴趣的元素。一条细细的蓝线在这次冒险中帮助你。

DOM Explorer 的右窗格(在图 2-11 中突出显示)提供了五个面板,每个面板都给我们不同的视角来观察左侧突出显示的元素。

9781430249832_Fig02-11.jpg

图 2-11 。使用 CSS 的应用程序开发人员将从 DOM Explorer 中的五个选项卡中受益匪浅

当你设计你的应用时,这些额外的标签是非常重要的。当您按照这本书的内容创建应用于 UI 中的元素的 CSS 样式时,这些样式将出现在这些选项卡中。

前两个选项卡非常相似。 Styles 选项卡显示了当前应用于所选元素的所有样式的列表,按照它们来自的样式表排列。跟踪样式选项卡也显示了当前应用的所有样式,但是现在它们是按照 CSS 属性排列的。我发现“跟踪样式”选项卡更有帮助。布局选项卡显示了一个叫做盒子模型的东西,我们将在第五章中讨论。 Attributes 选项卡允许您向所选元素添加 HTML 属性,最后 Events 选项卡显示与所选元素相关的任何 JavaScript 事件。

调试

调试是 Visual Studio 最强大的功能之一。整个执行周期可以一行一行地进行,在应用程序运行时可以观察甚至修改值。深入的调试当然超出了我们的范围,但是我希望简短的介绍将有助于说服或鼓励您选择工具。

当需要运行你的应用程序并观察它的行为时,你有几个选择。标准工具栏上的调试目标选择框如图 2-12 所示,允许您在本地(本机)、远程机器或模拟器上运行应用程序。

您可能通常会在本地机器上调试应用程序。本地跑是最快最简单的路线。当您想要定位另一台机器时,您可以选择远程机器,当您需要模拟开发机器上没有的特性或环境条件时,您可以选择模拟器。

模拟器可以让你模拟触摸、地理位置、屏幕大小和屏幕分辨率。

9781430249832_Fig02-12.jpg

图 2-12 。Visual Studio 允许您在本地计算机、远程计算机或模拟器中调试应用程序

到目前为止,我们讨论的所有内容都涉及到 Visual Studio 来编写和编辑驱动应用程序的原始代码。这当然是典型的开发方法,但是历史已经表明许多公司尝试实现可视化工具来为我们编写代码。就我而言,我从未被打动过。我看到的每一次尝试都以某种方式失败,最终阻止我使用它,并迫使我回到 Visual Studio 中编辑原始代码。也就是说,直到混合。

Blend 是 Visual Studio 2012 附带的免费产品。它甚至附带了 Visual Studio Express 2012,这也是免费的,所以你可以使用 Blend 而不用支付一分钱。Blend 不同于 Expression Blend。Expression Blend 是一个设计 XAML 组件的工具,但 Blend 是一个设计 XAML 或 HTML/CSS 格式的 Windows 8 应用程序的工具。

Blend 是一个不可思议的工具。大多数视觉设计者强迫用户区分设计模式和执行模式;视图以一种模式设计,然后执行程序来查看结果。在 Blend 中,你总是在设计执行模式 。您的应用程序由 HTML、CSS 和 JavaScript 组成,在 Blend 中运行,就像在机器上运行一样。因此,Blend 可以给你一个动态的 DOM(就像 Visual Studio 的 DOM Explorer 一样,只是它总是动态的!)而且它可以带来你所有的真实数据。在图 2-13 中,你可以看到融合的效果。虽然一开始你可能不会注意到,但是图 2-13 中的网格项目块是从 JavaScript 数据中动态加载的。

9781430249832_Fig02-13.jpg

图 2-13 。图 2-8 中的 网格 app,现在却在交融中打开

当你点击一个视觉元素,比如一个灰色的图块(在图 2-14 中高亮显示),Blend 认为你想要改变它的设计,所以它渲染典型的选择矩形和手柄来调整它的大小。如果我们拖动一个句柄并调整对象的大小,那么决定该图块大小的 CSS 将被修改,并且您将看到所有其他图块的大小也发生了变化。

9781430249832_Fig02-14.jpg

图 2-14 。Blend 运行您的应用程序,但可以设计一个元素

正如我所说的,当你点击一个磁贴时,Blend 假设你对高亮显示磁贴感兴趣,这样你就可以设计它,但是你可能想充当应用程序的用户,并在你点击时实际导航。这就是交互模式的作用。在文档区的右上角,你会发现一个类似于图 2-15 的交互模式图标。激活交互模式会通知 Blend 你想表现得像一个用户,并且实际上使用该应用。

9781430249832_Fig02-15.jpg

图 2-15 。互动模式图标 在交融

最棒的是,当您再次单击交互模式按钮返回到设计模式时,Blend 会保持您的应用程序状态,并允许您从那里继续设计。

也许 Blend over Visual Studio 最重要的贡献是它让您在操作底层样式 HTML 和 CSS 代码时以可视化方式工作。您可能已经有足够的 CSS 经验,知道它的声明可能相当复杂。应用于任何给定元素的样式可以从任意数量的样式规则向下级联,每个规则覆盖下一个规则。尽管这个结构相当复杂,但是当你在 Blend 中改变一个属性时,它能够改变正确的样式。

此外,图 2-16 中的所示的【应用的样式规则】窗格(通常位于 Blend 工作区的右上角)给出了所有应用于各种样式表的 CSS 样式规则的列表。

9781430249832_Fig02-16.jpg

图 2-16 。应用的样式规则窗格 显示了应用于所选元素的整个样式层次

当您需要创建自己的全新样式规则时,样式规则选项卡 ( 图 2-17 )列出了当前页面引用的所有样式表,明确指出新样式将位于哪个样式表中,并让您有机会更改它。

9781430249832_Fig02-17.jpg

图 2-17 。样式规则页签 表示将在哪个样式表中创建新规则

我喜欢 Blend 的最后一点是 3 窗格视图,它非常适合同时编辑 HTML 文件及其相关的 CSS 和 JS 文件。

然而,有一点需要注意,Blend 在 JavaScript 方面并不出色。如果您正在处理编程任务,请使用 Visual Studio。幸运的是,这两个工具都共享一个公共的项目格式,所以它们之间的切换是无缝的。事实上,Visual Studio 提供了一个“以混合方式打开”的选项(图 2-18 ),右击一个项目即可使用。

9781430249832_Fig02-18.jpg

图 2-18 。项目快捷方式使从 Visual Studio 切换到 Blend 变得快速而简单

分发您的应用程序

当你完成第一个应用程序时,这是多么美好的一天。毫无疑问,你会有很多的自豪感和对美元符号的憧憬。在写这篇文章的时候,我在 Windows 商店里有两个应用程序,我希望能写更多。

将你的应用提交到 Windows 应用商店并不是一件困难的事情。过程非常简单,认证要求很明确,沿途的反馈也很有帮助。我不会花时间详细描述商店提交过程,因为商店几乎会全程牵着你的手。不过,我会介绍它,带你进去。

此外,当您的应用程序处于开发阶段并且在发布之前,您可能需要将其安装在另一台设备上进行测试,因此我也将向您展示如何进行测试。

侧装

在设备上安装 Windows 8 商店应用而不使用 Windows 商店的行为通常被称为侧装。这绝对是一个受支持的场景,我会让你知道怎么做。

显然,您可以将源代码复制到另一个安装了 Visual Studio 的系统中,打开项目并运行它。这将有效地把你的应用程序安装到第二台设备上。然而,并不是每个设备都有 Visual Studio,Windows RT 设备不能有 Visual Studio。不过,还有另一种方法。如果您想在应用程序完成之前进行练习,可以从一个默认的项目模板开始。以下是将你的应用下载到另一台设备的步骤:

  1. 在开发计算机上的 Visual Studio 中打开您的应用程序。

  2. Choose Create App Packages from the Store menu (the Store menu is under the Project menu in professional versions of Visual Studio) as shown in Figure 2-19.

    9781430249832_Fig02-19.jpg

    图 2-19 。商店菜单中的创建应用程序包选项

  3. Choose No when you are asked Do you want to build packages to upload to the Windows Store? as shown in Figure 2-20. Click Next.

    9781430249832_Fig02-20.jpg

    图 2-20 。如果您知道您只打算下载这个版本的应用程序,请选择“否”

    image你可以在http://aka.ms/devlicenseinfo获得更多关于开发者许可的信息,在http://aka.ms/sideloading获得更多关于侧装的信息。

  4. 对于选择和配置包步骤,默认值应该是好的。如果您需要针对不同的处理器架构,您可以这样做,如果您不知道这意味着什么,那么就不要去管它,您应该没问题。单击创建。

  5. 包创建应该完成并指明位置。按确定。

  6. The package that gets created consists of a folder and an .appxupload file. The .appxupload file is for uploading to the Windows Store when you’re ready to submit it, but the folder is what you want for installing on another device. Use whatever means necessary to get the entire contents of that folder (Figure 2-21) copied to another device.

    9781430249832_Fig02-21.jpg

    图 2-21 。创建后的示例应用程序包。ps1 文件负责安装打包的应用程序

  7. 在新设备上,您只需右键单击Add-AppDevPackage.ps1文件并选择使用 PowerShell 运行。PowerShell 将启动并询问您几个问题,您可以接受默认设置。

这就是相对简单的侧向装载过程。

当然,为了扩大你的覆盖范围并避免在目标机器上要求开发者许可,你需要将你的应用提交到 Windows 应用商店。

发布到 Windows 商店

Windows Store 将让你的应用出现在数千万(很快会是数亿)消费者的眼前。如果你提供给他们的生活增加价值的应用程序,他们会很高兴地安装并使用它,如果你决定收费,他们甚至可能会放弃一些零钱。

要完成提交应用程序的过程,请转到http://dev.windows.com并按照说明获取您的开发者帐户。设置好之后,请遵循以下一般步骤:

  1. 按照与创建用于侧面加载的包相同的步骤构建应用包,直到您进入创建向导的第一个屏幕,在该屏幕中,它会询问您是否要构建要上传到 Windows 应用商店的包。很明显,这次你会对这个问题做出肯定的回答。
  2. 回到dev.windows.com,找到并点击 Windows 应用商店应用、仪表板,然后提交应用。
  3. 填写关于你的应用程序的大量信息,并在适当的步骤中上传你在步骤 1 中生成的.appxupload文件。

有关提交应用程序的完整流程的更多信息,请参考http://aka.ms/appsubmit

摘要

欢迎来到极其激动人心的 Windows 8 开发世界。

在本章中,您已经了解了 Windows 8 的体系结构,它支持广泛的计算机体系结构,以及一套有价值的工具和开发语言。所有这些,至少部分是由一种新的编程模型和一种叫做 WinRT 的现代 API 结合在一起的。

然后,您将接触到世界一流的工具,在您构建应用程序的每一天,它都将是您最好的朋友。广受欢迎的 Visual Studio 的最新版本将 Windows 8 商店应用程序邀请到其目标项目中,并从一些好的项目模板开始,让你在几秒钟内从零到完成产品。

Visual Studio 还欢迎 Blend 作为一个免费的伴侣来帮助应用程序的可视化设计。这两个工具共享一个通用的项目格式,使得设计和开发之间的协作对每个人来说都是流畅的体验。

最后,向您介绍了在本地运行应用程序、在另一台设备上安装应用程序以及将应用程序提交到 Windows 应用商店的选项。

我希望在读完前两章后,你觉得自己至少具备了开始设计和开发你的第一个应用程序的基本技能。还有更多的东西要学,也有很多可以学习的资源。对于 CSS 部门,只要坚持住,因为我们就要深入下去了。

三、选择器和样式规则

image 注意 CSS 不过是样式规则的集合,每个样式规则都由一个选择器和一个定义组成。不要让事情变得更复杂。

样式规则的选择器决定它影响什么,而定义决定它如何被影响。

因此,正如 HTML 的全部工作是定义文档的结构一样,CSS 的全部工作是对该结构进行布局和样式设计,使其在应该出现的地方出现。

通过结合 HTML 的文档对象模型(DOM)和 CSS 的元素选择功能,我们有了一种非常有效且相对独特的方式来表达潜在的复杂结构,然后在该结构中单独设计独特的元素集,而不会过于模糊或重复。

我称之为相对独特,因为许多其他 UI 语言的样式往往与文档结构混在一起。然而,对于 HTML 和 CSS,两者可以保持分离。其优势(除了对开发人员来说更清晰)是能够轻松地交换样式表,并在这样做时,完全改变应用程序的布局和风格。

因此,CSS 的强大之处在于它能够定义样式规则,然后确定该规则应该应用于 UI 中的哪些元素。

在图 3-1 中,你可以找到领先于所有其他应用的应用:Windows 应用商店应用。

9781430249832_Fig03-01.jpg

图 3-1 。Windows 应用商店 app

这个应用程序有内容,但也有很多风格。该应用程序的标题是一个更大的字体和定位;这些应用程序有图像、标题和背景颜色,页面上的一切都有一个非常有意识的布局。总的来说,该应用程序有很好的内容和很好的内容呈现。这才是我们真正的目标。

样式格式和位置

CSS 适用于或描述 HTML。实际上,它一般描述 XML,但就我们创建 Windows 8 应用程序而言,HTML 是我们唯一的考虑因素。这意味着,任何时候你创建一个 HTML 文件,并希望用样式影响该文件中的元素,你需要编写和应用一些 CSS。

这些样式可以存在于三个地方:

  • 在一条直线上的
  • 在嵌入的样式表中
  • 在外部样式表中

内嵌样式

内联样式是在样式属性中定义的,该属性直接添加到它们应该影响的元素中。

内联样式通常被认为是糟糕的形式,因为它们混合了项目中的结构和样式,很快会变得难以处理。我通常从不使用内联样式,我强烈地感觉到,即使有,也是极少的情况下,它们应该被投入生产。它们可能对一些开发人员有帮助,比如快速原型或故障排除设计,但是它们不应该用在最终产品中。清单 3-1 展示了内嵌样式的样子。

清单 3-1 。 一个简单的 HTML5 文档,在 div 标签上有一个内嵌样式属性

<!-- default.html -->
<!DOCTYPE html>

<html lang="en" FontName2">http://www.w3.org/1999/xhtml ">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <divstyle="font-weight: bold;" ></div>
</body>
</html>

嵌入样式表

嵌入式样式表是在它们影响的页面上定义的。一个style元素被添加到页面的head元素中,并包含样式规则来确定如何将样式属性应用于各种元素。嵌入式样式表通常没有第三个选项常见,在 Windows 8 应用程序中应该很少见。清单 3-2 是一个嵌入式 CSS 样式表的例子。

清单 3-2 。 一个简单的嵌入了样式标签的 HTML5 文档

<!-- default.html -->
<!DOCTYPE html>

<html lang="en" FontName2">http://www.w3.org/1999/xhtml ">
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        #myDiv { font-weight: bold; }
    </style>
</head>
<body>
    <divid="myDiv" ></div>
</body>
</html>

外部样式表

最后,外部样式表是定义和应用样式的最佳方法。对于外部样式表,受影响的 HTML 文件不会被打印出来。事实上,唯一的痕迹是对样式表的引用,它只需要在head元素中使用一行代码,剩下的 HTML 代码完成它的工作,提供文档的结构。使用外部样式表的另一个主要优点是可以轻松地动态交换它们,以支持多主题、多语言甚至多平台。

清单 3-3 展示了一个引用外部样式表的 HTML 文件的好例子。

清单 3-3 。 一个简单的 HTML5 文档,引用了一个外部 CSS 样式表

<!-- default.html -->
<!DOCTYPE html>

<html lang="en" FontName2">http://www.w3.org/1999/xhtml ">
<head>
    <meta charset="utf-8" />
    <title></title>
    <link href="default.css" rel="stylesheet" />
</head>
<body>
    <div id="myDiv"></div>
</body>
</html>

/* default.css */
#myDiv {
    font-weight: bold;
}

这些样式表文件(。css)可以保存在任何地方,只要它们可以通过来自 HTML 页面的 HTTP 请求来访问。你可以链接到一个存储在互联网上完全不同的服务器上的样式表,或者它可以在你的 web 项目的中心文件夹中(也许叫做cssstyles,或者它可以就在你的 HTML 文件旁边,你可以在链接的href属性中使用绝对引用或相对引用。

在一个 web 项目中,将所有样式表放在一个中心位置是一个相当强的惯例,但这也很常见,尤其是在创建单页面 web 应用程序时,为项目中的每个 HTML 页面创建一个样式表,这是 Windows 8 应用程序中的惯例。当你设计你的 Windows 8 应用时,你可以选择把 CSS 文件放在你选择的任何地方,但是遵循惯例是一个好的实践。内置的 Windows-8 项目模板之一是导航应用程序模板,它遵循这一约定,将每个页面的 CSS 文件、HTML 文件和 JavaScript 文件放在各自的文件夹中,这些文件夹位于pages文件夹内。

基本样式规则语法

外部样式表的内容(就此而言,还有嵌入的样式表)很简单——只不过是由一个接一个的样式规则组成的大列表。有时候,样式规则可能会被媒体查询块包装起来,但是我们将稍后再讨论这个主题。

清单 3-4 展示了填充了一些规则的样式表(无论是外部样式表还是嵌入样式表)看起来会是什么样子。

清单 3-4 。 典型格式为样式规则

selector {
    property: value;
    property: value;
    property: value;
}

selector {
    property: value;
    property: value;
    property: value;
}

selector {
    property: value;
    property: value;
    property: value;
}

对于一些较短样式的规则,你可能像我一样,宁愿放弃规则之间的换行,而在一行上格式化你的规则,更像清单 3-5 中的。

清单 3-5 。 当样式规则简单时,用于节省垂直空间的更紧凑的格式

selector { property: value; property: value; }
selector { property: value; property: value; }
selector { property: value; property: value; }

这样可以节省一些垂直空间,也许还可以延长鼠标滚轮的寿命,但是和它的姐妹技术 HTML 一样,CSS 忽略了多余的空白,所以你可以随意设置格式,并且知道它会被同样地解释。

另一个典型且非常有用的约定是样式规则的缩进,它只影响前面样式规则下面的元素。在命令式编码语言中,缩进被广泛用于向开发人员传达代码结构,使其更易于阅读。在 CSS 中,缩进的代码表示样式规则之间的层次关系。记住空白被忽略,所以这个缩进对功能没有影响。请注意清单 3-6 中的第二个样式规则是如何包含与前一个规则相同的选择器(“selectorA”)的,以及一些更多的细节。这意味着它在它前面的规则的上下文中,这就是缩进所表示的。您将在本书的示例代码中看到这种约定。

清单 3-6 。 缩进严格地作为表示层次的视觉辅助

selectorA {
    property: value;
    property: value;
    property: value;
}

    selectorA selector1 {
        property: value;
        property: value;
        property: value;
    }

selectorB {
    property: value;
    property: value;
    property: value;
}

你现在知道什么是风格规则了,是时候学习如何作曲了。我们将从讨论选择器开始。

选择器

想象你正在用一个典型的文字处理器工作。当您完成了文档的撰写和编辑后,您的工作就变成了格式化。要确定文档各部分的格式,需要采取两个步骤:用鼠标拖动选择要格式化的区域,然后应用各种样式规则,通常是通过单击命令按钮或键盘快捷键。例如,您可以选择整个第一段,然后决定将字体大小增加到 16 磅。或者,您可以只选择一个单词,并将其设置为带下划线。

这些正是您将对 CSS 采取的步骤,只是您使用选择器进行选择,并使用样式属性应用样式。您的选择器指定了您想要选择的 HTML 元素,并且相关联的样式属性决定了该选择应该发生什么。

因此,编写能够准确选择您想要的内容的选择器显然是非常重要的一步,我恳请您不要跳过这一部分。事实上,我发现比那些缺乏格式化技巧的开发人员更缺乏 CSS 选择技巧的开发人员。这相当于浪费时间、空间和复杂性,要么用不必要的类和 ID 装饰符过度定义 HTML,要么在 CSS 中使用冗余或冗长的样式规则。任何一个失误都会增加项目的复杂性,即使网站或应用程序运行良好,也会有明显的不利影响。

选择器是一个表达式,它被求值并产生一个零到多个 DOM 元素(或者伪元素,但我们稍后会讲到)的列表。

例如,对选择器的评估可能导致选择页面上的每个div元素、body中的第一个p或页面footer元素。然而,选择器可以变得非常具体,导致排序列表中的每三个列表项(li)或称为myDivdiv第三段的第一个字母。

定义选择器的目标是选择您想要的,仅此而已。定义了一个选择器和样式规则,却发现规则影响的元素比预期的要多,这是很常见的。

有几种不同的方式来引用同一个元素。你可以通过它的类型(也就是它的标签名或元素名,即divpvideobody等)来引用它。).如果它有唯一的id属性,你可以引用它。您可以通过它的class属性中的任何值来引用它。或者,最后,你可以用其他创造性的方法来引用它,我们会在适当的时候讲到。

在我们深入研究不同的选择技术之前,让我们定义几个术语:

  • style rule。样式规则是一个完整的声明,它将决定哪些元素将受到样式的影响,并定义将应用的样式。它由选择器和声明块组成。
  • **selector****。**选择器是在 DOM 中定位一个或多个元素的模式。选择器可以由多个简单的选择器和组合子组成。
  • **combinator****。**组合符是一个符号,它定义了左边的简单选择器所指向的元素和右边的简单选择器所指向的元素之间的上下文关系。
  • **declaration block****。**样式规则的声明块定义了样式属性及其值,它们将应用于样式规则选择器的结果。

图 3-2 说明了这些术语。

9781430249832_Fig03-02.jpg

图 3-2 。CSS 样式规则的剖析

现在,让我们学习选择元素的各种方法。

类型选择器

你应该知道的第一个选择器是型选择器。类型选择器只是 HTML 元素的名称;使用一个会选择该类型的每个元素。清单 3-7 中的选择器将定位页面上的所有div元素,并将文本加粗。

清单 3-7 。 一个针对文档中每个 div 的类型选择器

/* CSS snippet */
div {
    font-weight: bold;
}

清单 3-8 将整个正文中的所有文本加粗。从技术上讲,这将尝试定位所有的 body 元素,但是让我们希望你只有一个!

清单 3-8 。 针对文档正文的类型选择器

/* CSS snippet */
body {
    font-weight: bold;
}

如果您没有指定类型,而是使用星号(*),那么您使用的是通用类型选择器,它匹配所有类型。清单 3-9 中的 CSS 将匹配整个页面上的每个元素,并将其字体设置为粗体!

清单 3-9 。 显式使用通用类型选择器

/* CSS snippet */
* {
    font-weight: bold;
}

这个通用选择器本身并不经常使用,但是理解它是很重要的,原因我们很快就会谈到。

不要忘记,这些类型选择器单独使用时,将匹配该类型的任何和所有匹配元素。为了只选择一个 div 元素,您必须更加具体(我们将在后面介绍更多)。

这很重要。在表达式中,类型选择器必须位于任何其他选择器之前。如果你已经做过 CSS 开发,这可能会让你大吃一惊。你可能使用过选择器,比如清单 3-10 中的选择器。

清单 3-10 。 一些选择器其中包含了隐式使用的通用类型选择器

/* CSS snippet */
.first {
    font-size: 18pt;
}

#firstName {
    border: 1px solid black;
}

:hover {
    color: green;
}

在这个例子中,在类选择器、ID 选择器和伪类选择器之前似乎没有类型选择器。但是请注意,如果您没有显式指定类型选择器,那么通用类型选择器(*)会隐式地为您分配。因此,清单 3-11 中的选择器与前面的例子是一样的。

清单 3-11 。 同样的三个规则加上一个显式的通用类型选择器

/* CSS snippet */
*.first {
    font-size: 18pt;
}

*#firstName {
    border: 1px solid black;
}

*:hover {
    color: green;
}

这是有意义的,因为你想用类似于#firstName的东西来表示的是任何带有firstNameid的元素。

班级选择器

与类型选择器不同,类选择器除了简单地声明元素之外,还需要你在 HTML 文件中做一些工作。具体来说,你需要用一个类来修饰你的元素。清单 3-12 展示了给一个div元素一个important类的样子。

清单 3-12 。 一个指定了类的 div 元素

<!-- HTML snippet -->
<div class="important"></div>

理解类选择器的预期用途很重要。许多开发人员在应该使用 ID 选择器的地方使用了它们(即将推出)。

添加到 HTML 元素中的类名通常应该是与它们相关的元素的形容词。类描述了它们的元素的一些永久或暂时的特征。当一个div包含应该在首页突出显示的内容时,它可能有一个featured类。当用户选择一个列表项时,它可能有一个selected类。或者一个视频可能有一个hidden类,当它应该等待用户动作来显示它时。

注意,我说过这些类可能是一个瞬态特征。在您的 HTML 应用程序中,您可能会根据应用程序的逻辑使用 JavaScript 在某些元素中添加或删除类。当用户选择一个元素时,JavaScript 事件可能会触发,并将selected类添加到该元素中。这样做时,元素会突然采用适用于所选元素的样式规则。例如,在清单 3-13 中,带有mydividdiv并没有启动类,但是当 JavaScript 代码片段中的代码触发时(这可能是对用户所做的事情的反应),将bigAndBold类添加到元素中,由该样式规则定义的所有样式属性突然生效。

清单 3-13 。 以编程方式添加类

<!-- HTML snippet -->
<div id="mydiv">Lorem ipsum</div>

/* CSS snippet */
.bigAndBold {
    font-size: large;
    font-weight: bold;
}

// JavaScript snippet
document.querySelector("mydiv").className = "bigAndBold";

用一个类值来修饰你的元素本身并不会对你的元素做任何事情,除非这个类为它定义了一个样式规则。将视频元素的类设置为hidden并不会隐藏它,除非你也为隐藏的类编写一个样式规则,比如display:nonevisibility:hidden

要将某个类作为所有元素的目标,只需在类名前加一个句点(。)在您的选择器中,如清单 3-13 中的所示。

清单 3-13 。 一个引用元素的类选择器带有一个类【重要】

/* CSS snippet */
.important {
    color: red;
}

元素不限于单个类。例如,清单 3-14 中的 HTML 标记定义了三个不同的类,完全有效。

清单 3-14 。 一个元素定义了三个类

<!-- HTML snippet -->
<div class="important featured hidden"></div>

在这种情况下,我们描述的是一个重要的、有特色的、隐藏的div。这没什么不好。

类似地,也许很明显,同一个类名可以修饰任意多的元素。重要的是你永远不要使用一个类来唯一地标识一个元素。唯一地标识元素是id属性和 ID 选择器的工作,我们很快就会看到。当您试图指定一组具有共同点的实体时,应该使用类。类本质上与元素集相关。

如果内容的结构可能会改变,那么应该用类选择器来代替类型选择器。当您在选择器中指定一种类型时,比如div,您就使您的样式依赖于文档结构,并使将来更改该结构变得更加困难。例如,你可以从定义菜单项的div标签列表开始,如清单 3-15 所示。

清单 3-15 。 使用 div 定义的菜单

<!-- HTML snippet -->
<div class="menu">
    <div>Home</div>
    <div>About</div>
    <div>Products</div>
    <div>Services</div>
    <div>Contact</div>
</div>

然而,你应该能够预见这种变化的可能性,比如清单 3-16 中的无序列表。

清单 3-16 。 同一个菜单现在被定义为列表项的无序列表

<!-- HTML snippet -->
<ul class="menu">
    <li>Home</li>
    <li>About</li>
    <li>Products</li>
    <li>Services</li>
    <li>Contact</li>
</ul>

在这种情况下,您可以通过按类(menu)引用菜单来保持 CSS 样式的抽象性,而无需指明类型。那么可以在不影响样式的情况下更改实际使用的元素类型。

所以你应该从清单 3-18 中选择一个,而不是清单 3-17 中的样式规则。

清单 3-17 。 一种类型菜单元素的具体引用方式

/* CSS snippet */
div.menu {
    /* menu styles */
}

清单 3-18 。 一种更好、更抽象的指代菜单元素的方式

/* CSS snippet */
.menu {
    /* menu styles */
}

第一个要求你有一个menu类的div。第二个也是首选的例子只需要你有类menu的任何元素。第一个例子只适用于第一个例子(使用div元素的例子),但是第二个例子适用于两个例子。

类选择器也可以相互链接,只匹配指定类的所有元素。

ID 选择器

我提到元素的类值应该被认为是元素的形容词——比如hiddenbiggeremphasizedheader。元素的id值应该是它的名字,并且必须是唯一的。一个img标签可能有mainLogoid,这给了我们一个明确的定义,以供将来参考,并且整个页面上不会有其他的mainLogo

您也必须确信这一点,因为如果您获得具有相同id值的多个元素,可能会出现一些奇怪的行为。

当您通过类引用元素时,您可以期望找到从零到许多的任何位置,但是当您通过 ID 引用元素时,您应该只期望一个,因为正如我们已经提到的,ID 应该总是唯一的。

要按 ID 选择元素,可以在元素前使用井号(#)。例如,清单 3-19 显示了一个选择器,它将选择一个id值为mainLogo的元素,并将其width设置为80px

清单 3-19 。 一个 ID 选择器,它应该只匹配一个元素

/* CSS snippet */
#mainLogo {
    width:80px;
}

没有必要明确指出类型,因为 ID 选择器总是引用单个特定的元素。

ID 选择真的没有比这更多的了。很简单。

属性选择器

到目前为止,我们已经看到了如何通过类型、类和 ID 来选择元素。然而,元素通常都有属性,可以根据这些属性的值来选择它们。

可以想象,这开启了很多可能性。HTML 元素的数量是有限的,但是有大量可能的属性,甚至每个属性可能有更多的值。

查看清单 3-20 中的选择器,它将为页面上所有的 ListView 控件设置 120 像素的左边距。

清单 3-20 。 匹配 ListView 控件的属性选择器

/* CSS snippet */
 [data-win-control='WinJS.UI.ListView'] {
    margin-left: 120px;
}

这里最大的优势是我们的 HTML 元素不需要比现在更具描述性。 div 已经通过属性声明它是一个 ListView,所以我们可以使用它,而不是浪费字节来添加 ID 或类属性。

最后一个例子使用了等式选择器([=])来检查data-win-control属性的值是否为WinJS.UI.ListView。不过,也可以使用其他属性选择器。

如果您只在方括号中指定了一个值,它将检查该属性是否存在,而不管它的值是什么(或者它是否有值!).清单 3-21 将把所有具有required属性的input元素的文本改为红色。

清单 3-21 。 一个简单检查某个属性是否存在的属性选择器

/* CSS snippet */
input[required] {
    color: red;
}

请记住,HTML5 中的required属性不像在 HTML 的以前版本中那样需要值。因此,这种存在比较对于这些“无价值”的属性是有帮助的,并且可能还有许多其他原因。

当指定属性的值完全等于指定值时,使用[|=]连字符选择器将会匹配,但如果属性的值中有后跟连字符的指定值,它也会匹配。因此清单 3-22 中的属性选择器将匹配阿郎值为enen-usen-au的段落,但不匹配es

清单 3-22 。 所有的 lang 属性都带有英语的派生词

/* CSS snippet */
p[lang|='en'] {
    direction:ltr;
}

^=]选择器被称为前缀选择器 ,但我记得是“开头为”。使用这个来查看属性是否有以某个值开始的值。清单 3-23 将为所有 ID 以item开头的div元素添加一些左边距。

清单 3-23 。 【始于】选择器

/* CSS snippet */
div[id^='item'] {
    margin-left:10px;
}

这将匹配itemitem1item02item-3等等,但不会匹配selecteditem

[]选择器也是类似的。它被称为后缀选择器 (我称之为“ends with”),当属性以您指定的值结束时,它将进行匹配。清单 3-24 将匹配selecteditemfirstitemitem,但不匹配itemOne.

清单 3-24 。 【结尾用】选择器

/* CSS snippet */
div[id$='item'] {
    margin-left:10px;
}

子串选择器 [ *= ]更容易记为“包含”,当属性值的任何部分匹配时,它就匹配。清单 3-25 将匹配所有 ID 包含字符串‘sidebar’的 div 元素。

清单 3-25 。??【包含】选择器

/* CSS snippet */
div[id*='sidebar'] {
    margin-left:10px;
}

最后,有一个空格选择器 [ ∼= ],它将在一个空格分隔的值列表中匹配您的值。这个有时会非常有用。看看清单 3-26 中的 span,它有一个名为data-food-types,的自定义属性,该属性将在一个空格分隔的属性值中包含类似meatvegetabledairy的内容。在这种情况下,空白选择器非常适合确定meat是否是列表中的一个值。值必须完全匹配;它们不能是部分匹配。

清单 3-26 。 空白选择器的一个用例

<!-- HTML snippet -->
<span data-food-types="dairy meat">meal</span>

/* CSS snippet */
span[data-food-type∼='meat'] {
    font-style:italic;
}

像类和 ID 选择器一样,属性选择器默认为通用类型选择器,所以下面两行是相同的:

[data-win-control='WinJS.UI.ListView']
*[data-win-control='WinJS.UI.ListView']

顺便说一下,在这种情况下,让显式类型选择器(div)处于关闭状态非常有意义,因为data-win-control只会出现在div元素上。

您可以为任何可能描述一个HTML元素的属性创建一个属性选择器。对于 HTML,只有被识别的属性才被认为是有效的,但是对于 HTML5,任何被识别的属性或者任何以 data- 开头的属性都被认为是有效的,所以开发者可以自由添加以data-开头的自定义属性。可能的属性选择器的数量是无限的。

清单 3-27 展示了一些在使用 HTML5 的 Windows 8 应用程序中使用属性选择器的实际例子。

***清单 3-27 。***Windows 8 应用中的属性选择器示例

/* CSS snippet */
section[role=main] {
    /* styles to affect the main section */
}

[data-win-control] {
    /* styles to affect all Windows 8 control in the document */
}

[data-win-control^='WinJS.UI'] {
    /* styles to affect just the UI controls */
}
属性选择器
标志名字描述
---------
[=]平等匹配具有指定名称和值的属性的元素
[]存在匹配具有指定名称的属性的元素
&#124;=连字号匹配具有指定值或指定值后跟连字符的属性的元素
[^=]前缀匹配具有以指定值开头的属性的元素
[$=]后缀匹配具有以指定值结尾的属性的元素
[*=]子链匹配具有包含指定值的属性的元素
[∼=]空白匹配具有指定值或由空白包围的指定值的属性的元素

您可能会感兴趣地注意到,您实际上可以使用属性选择器通过 ID 来选择元素,但是这种形式很糟糕,因为有一个 ID 选择器就是专门为此设计的。

伪类和伪元素选择器

我希望你现在已经有了类的概念。记住,类是一个形容词。它描述了它所修饰的元素,并且是由您——开发人员——显式添加的。另一方面,伪类是固有的。它们是形容词,就像类一样,但是你不需要在 HTML 中指定任何东西。

例如,当用户悬停在一个表格行上时,单词 hover 可以用来描述该行,对吗?其中一个伪类是:hover(如您所见,伪类前面有一个冒号),只要用户将鼠标悬停在该元素上,就可以用它来选择该元素。向选择器中添加伪类比以编程方式向元素中添加类更容易、更简洁。

像其他选择器一样,可以单独指定一个伪类并调用默认的类型选择器。所以:hover*:hover是一样的,将匹配悬停在上面的任何元素。

伪元素的概念与伪类的概念非常相似。就像伪类的行为类似于类,但它是固有的,不需要由开发人员指定一样,伪元素的行为类似于元素,但它是固有的,也不需要由开发人员指定。

列表中的第一个列表项就是这样,不管你是否明确指定,对吗?其中一个伪类是:first-child,它将选择第一个列表项。这里,我们再次选择元素,而不必被迫编写无关的标记。

您可能会对伪类和伪元素之间的区别感到困惑,这是因为在 CSS3 之前的标准中语法没有区别。CSS3 引入了双冒号(::)语法来引用伪元素,并将单冒号(:)留给伪类。为了向后兼容,以前使用单个冒号的伪元素保留在规范中,所以在下面标准伪类和伪元素的完整列表中,您将会看到它们两次:::after, ::before, ::first-letter, ::first-line, ::selection, :active, :after, :before, :checked, :default, :disabled, :empty, :enabled, :first-child, :first-letter, :first-line, :first-of-type, :focus, :hover, :in-range, :indeterminate, :invalid, :lang(), :last-child, :last-of-type, :link, :not(), :nth-child(), :nth-last-child(), :nth-last-of-type(), :nth-of-type(), :only-child, :only-of-type, :optional, :out-of-range, :read-only, :read-write, :required, :root, :target, :valid, :visited.

除了标准的伪类和伪元素之外,还有一些特定于微软供应商的伪类和伪元素,在 Windows 8 应用中工作时,您应该熟悉它们。分别是:-ms-input-placeholder:-ms-keyboard-active::-ms-browse::-ms-check::-ms-clear::-ms-expand::-ms-fill::-ms-fill-lower::-ms-fill-upper::-ms-reveal::-ms-thumb::-ms-ticks-after::-ms-ticks-before::-ms-tooltip::-ms-track::-ms-value。供应商特定的伪选择器通常用于访问各种控件的子元素。

我不会带您浏览伪选择器的整个列表,但是我想突出几个我认为最有帮助的。

:词根

:root伪类有一个简单的功能,那就是在上下文中定位文档的根元素。例如,当 CSS 描述一个 HTML 文档时,根总是 HTML 元素。你永远不知道这个什么时候会派上用场,所以把它放在你的后口袋里。

*第一个字母

::first-letter非常适合在段落中创建首字下沉。我无法想象它还有什么其他用途,但是正如它的名字所表明的,它代表了它所应用的元素的文本中的第一个字母。请记住,有时伪类或伪元素被显式地附加到选择器中的元素上,如在p::first-letter中。其他时候,它是隐含在div ::first-letter中的。不要错过其中的细微差别。前者的意思是“段落标记的第一个字母”。后者在 div 后面有一个空格,因此意味着“作为 div 后代的每个元素的第一个字母”。

清单 3-28 定义了::first-letter伪元素最常见的用法——创建首字下沉。图 3-3 展示了最终的首字下沉。

9781430249832_Fig03-03.jpg

图 3-3 。样式定义创建首字下沉效果

清单 3-28 。 使用::首字母伪元素定位段落中的首字母

/* CSS snippet */
.dropCap::first-letter {
    font-size: 500%;
    float: left;
    line-height: 0.8em;
    padding: 0 4px 0 0;
    font-family: Serif;
    font-weight: bold;
    position: relative;
    left: -3px;
}

:勾选

:checked 是一个伪类(你可以通过前面的单个冒号来辨别),它会将选中的复选框(或单选按钮)限制为已经被选中的复选框。清单 3-29 和图 3-4 展示了:checked伪类的作用。

9781430249832_Fig03-04.jpg

图 3-4 。标记为选中的复选框已获得边框样式

清单 3-29 。??:选中的伪类选择器在起作用

<!-- HTML snippet -->
    <div id="checkboxes">
        <input type="checkbox" />
        <input type="checkbox" checked />
        <input type="checkbox" />
        <input type="checkbox" checked />
        <input type="checkbox" />
    </div>

/* CSS snippet */
#checkboxes :checked {
    border: 1px solid red;
}

::之前,::之后,和内容

content样式属性结合使用的::before::after 伪元素,用于在选择器的目标元素之前或之后注入一些内容。首先,您可能会想知道这个功能在 CSS 中是干什么的。毕竟,这看起来像是应该由 HTML 和/或 JavaScript 处理的内容问题。

然而,在有些情况下,内容的注入实际上更像是一个样式问题。假设您想要在悬停的段落旁边呈现一个小的补充字形,以向用户指示哪一个是焦点。或者,您可能希望在用户已经访问过的链接旁边显示一个复选标记。如果没有::before::after伪元素和content属性,这两者都是不可能的。

关于content属性,至少还有一件有趣的事情。它允许使用一个attr()函数来引用上下文中元素的一个属性值。例如,看一下清单 3-30 ,当你悬停在它上面时,它会在每个链接旁边呈现一个弹出工具提示,包括链接的标题。

清单 3-30 。::. after 伪元素,用于呈现悬停链接的工具提示

/* CSS snippet */
a:hover::after {
    content: attr(title);
    background-color: lightyellow;
    border: 1px solid black;
    color: black;
    position: relative;
    left: 10px;
    white-space: nowrap;
    padding: 5px;
}

:必需的

这个:required伪类被大量用于向标记为必需的字段添加样式。清单 3-31 显示了一个例子。通常,web 开发人员会用红色边框、可选背景色或附赠符号来修饰必填字段。如果与我们刚刚学习的::before::after伪元素以及content属性结合使用,可以将符号添加到必填字段,而不需要任何额外的标记。

清单 3-31 。 一个 HTML 元素,有一个必需的属性和一个 CSS 规则来设置它的样式

<!-- HTML snippet -->
<input type="text" required />

/* CSS snippet */
input:required {
    border: 1px solid red;
    color: red;
}

::-ms-expand

::-ms-expand伪元素表示呈现在选择控件上的小下拉箭头。

::-ms-浏览

通过使用::-ms-browse属性,可以将使用文件输入控件时呈现的浏览按钮作为目标。能够像这样瞄准子元素,可以对应用程序设计的细节进行非常精细的控制。

位置伪类

许多伪类都与元素在 DOM 中的位置有关。他们是:first-child, :first-of-type, :last-child, :last-of-type, :nth-child(), :nth-last-child(), :nth-last-of-type(), :nth-of-type(), :only-child,:only-of-type

这些位置伪类 非常有助于选择正确的元素,而不必用 id 或 class 属性来修饰 HTML 元素。你可以用它们来指代

  • 页面上的第一个 div
  • 每隔一行表格
  • 一节中的最后一段
  • 奇怪的菜单项
  • 每三个列表项目
  • 更多

您会注意到,这些伪类中大约有一半以-child为后缀,另一半以-of-type为后缀。-child不受限于元素类型,而-of-type则受限于元素类型。考虑清单 3-32 和清单 3-33 之间的细微差别。

清单 3-32 。 带有-child 后缀的位置伪类之一

/* CSS snippet */
div p:first-child {
    font-weight: bold;
}

清单 3-33 。 带有-of-type 后缀的位置伪类之一

/* CSS snippet */
div p:first-of-type {
    font-weight: bold;
}

清单 3-32 将选择“其同级中第一个子段的每个段落”,而清单 3-33 将选择“其同级中第一个段落的每个段落”。当然,这两个匹配的段落也必须是一个div元素的后代,因为选择器是以div开始的。

那么,你已经看到了first-childfirst-of-type伪类做了什么,并且你可能猜到了last-childlast-of-type做了什么。现在看看:nth-child():nth-of-type():nth-last-child():nth-last-of-type()。这些伪类是功能性的,这就是它们有括号的原因。

为了说明所有这些位置伪类,考虑清单 3-34 中的表格。

清单 3-34 。 一张桌子有五排

<!-- HTML snippet -->
<table id="myTable">
    <tr><td>Beans</td><td>2.7</td><td>67%</td></tr>
    <tr><td>Corn</td><td>1.7</td><td>40%</td></tr>
    <tr><td>Beets</td><td>2.9</td><td>77%</td></tr>
    <tr><td>Carrots</td><td>7.0</td><td>62%</td></tr>
    <tr><td>Celery</td><td>12.3</td><td>50%</td></tr>
</table>

如果我们的目标是选择所有的表格行并将它们的背景涂成灰色,我们可以使用。。。

/* CSS snippet */
#myTable tr {
    background-color: gray;
}

另一方面,如果我们的目标是只选择某些行,我们将使用first-last-nth-中的一个。

为了选择表格的第一行,我们将使用清单 3-35 中的。

清单 3-35 。 这个:第一个子伪类用来给表格中的第一行着色

/* CSS snippet */
#myTable tr:first-child {
    background-color: gray;
}

为了选择最后一个表格,我们将使用清单 3-36 中的。

清单 3-36 。 这个:last-child 伪类用来给表格中的最后一行着色

/* CSS snippet */
#myTable tr:last-child {
    background-color: gray;
}

为了每隔一行选择一行,我们可以使用清单 3-37 中的。

清单 3-37 。??:第 n 个子伪类,用于对表格中的每隔一行进行着色

/* CSS snippet */
#myTable tr:nth-child(2n) {
    background-color: gray;
}

现在,这个需要解释一下。:nth-child伪类的行为就像一个函数,您可以传入一个形式为an + b的公式。CSS 引擎会将一组以0开始的正整数插入到n的公式中。结果将是一组整数。CSS 将忽略负值和零值,并使用产生的正整数来确定哪些项目应该匹配。

在清单 3-37 中,我只提供了2n,它相当于2n + 0并计算为[0,2,4,6,8,...]0被省略,我们实质上是高亮显示每一个偶数行。这是一个常见的场景,所以 CSS 也定义了even关键字,并允许我们简单地使用#myTable tr:nth-child(even)来创建相同的效果。

然后考虑公式2n-1,它将计算出类似于[−1,1,3,5,7,9,...]的整数集。然后 CSS 会忽略1(因为它小于零),并将该样式应用于元素 1、3 和 5。就像even一样,CSS 定义了odd关键字来简化问题。

您传递给一个nth-伪类的公式可能会非常有趣。这里有一些例子。。。

第 n 个伪类的示例公式

2n /* every other (starting with the second) */
2n - 1 /* every other (starting with the first) */
3n /* every third */
3n + 3 /* every third starting with 3 */
-n + 3 /* only the first three */
n + 3 /* all, starting with the third */

最后,我们来看看:only-child:only-of-type伪类。清单 3-39 使用了它们中的每一个。

清单 3-39 。 示例使用:独生子女和:唯类型伪类

/* CSS snippet */
div p:only-child {
    font-size: larger;
}

div p:only-of-type {
    font-size: larger;
}

第一个规则将选择“div 中的段落,只要它是该 div 下的唯一元素”,第二个规则将选择“div 中的段落,只要它是该 div 下的唯一段落元素”。

:目标

您可以使用:target伪类向您的应用程序添加一些相当有趣的交互,而无需引入任何 JavaScript。

它是这样工作的。如果文档中有一个元素的id值与当前 URL 中的片段标识符相匹配,那么该元素将与:target伪类相匹配。

例如,如果您的 URL 是http://www.mysite.com/#image01,那么带有image01id的元素将匹配:target伪类。

片段标识符用于在单个文档中导航用户,所以通过使用这个伪类,您可以添加样式,让用户知道他的焦点在哪里或者他在做什么。

:not( )

最后要给大家看的是:非伪类 。这个是有用的,因为它颠倒了括号内的内容。在前面的例子中,我向您展示了如何使用。。。

#checkboxes :checked {
    border: 1px solid red;
}

我们可以颠倒这个逻辑,使用。。。

#checkboxes :not(:checked) {
    border: 1px solid red;
}

组合子

我们现在知道如何使用以下方法选择一个柠檬或一组元素:

  • 元素的类型
  • 元素的一个或多个类
  • 元素的唯一 ID
  • 匹配元素属性的存在或值的表达式
  • 一个或多个伪类
  • 一个或多个伪元素

这涵盖了很多情况,但这不是我们用选择器能做的全部。选择者可以在团队中工作。可以使用组合子将它们组合在一起,以指定元素之间的层次结构和可能复杂的逻辑关系,从而到达目标元素。

我们可以很容易地选择页面上的所有div元素,并在它们上面添加一些空间,方法是:

div {
    margin-top: 6px;
}

然而,如果我们实际上只想在一个节中的 div 元素之前添加空格,那么我们就必须使用一个组合符。我们实际上必须使用下降组合子,它看起来像清单 3-40 。

清单 3-40 。 两个简单样式的选择器被一个后代组合符(一个空格)隔开

/* CSS snippet */
section div {
    margin-top: 6px;
}

清单 3-40 中的选择器中有一个空格。它将sectiondiv分开,这在两者之间建立了一个层次关系。它表示只有作为section的子节点的div应该匹配。这个空间被称为派生组合子,我们将更深入地研究它和其他三个。

下降的

使用一个空格(˽)来表示一个后代组合符。

在两个选择器之间使用这个空格意味着:“选择匹配第二个选择器的所有元素,其中该元素是匹配第一个选择器的元素的后代”。听起来好像满嘴都是,但是看着也不难。一个例子将澄清这一点。

div p {
    padding: 2px;
}

前面的代码将在div内的所有段落标签周围添加一些填充。这意味着它们可以嵌套任意多级,并且可以位于任何div的内部。这是一个非常自由的选择器。

子组合子是一个大于号(>)。

子组合子类似于后代组合子,只是它更加具体。只有当右边选择器匹配的元素是左边选择器匹配的元素的直接后代时,子组合子才匹配。

当你忘记了子组合子,并且懒散地在你的选择器之间留出一个空间时,你可能会遇到麻烦。例如,div p的选择器将匹配任何一个div的子段落,当你的div下只有一层子段落时,这很好。然而,它也将匹配div的远祖p元素,这可能是也可能不是你想要的。

这就是子组合子的用武之地。它要求右边的元素是左边元素的直接子元素。

一般同胞

后代和子组合符表示元素之间的垂直父子关系,但是兄弟组合符 ( )表示同一父元素的子元素之间的水平关系。

一般的兄弟姐妹意味着兄弟姐妹的顺序,但没有说兄弟姐妹之间有多近或多远。给定A ∼ B,AB必须有相同的父元素,并且B必须在A之后,但是中间可能有许多元素。

相邻的兄弟姐妹

相邻兄弟组合子 ( +)类似于一般的兄弟组合子,只是更具体一些。相邻的兄弟元素表明,与任一侧的选择器匹配的元素不仅是兄弟元素,而且它们彼此紧挨着,并按照指定的顺序排列。

你可能不会像其他人一样经常使用相邻兄弟组合符,但是当你需要它的时候,它是一种很好的资产。清单 3-41 显示了一个这样的例子,如果一个H1元素紧跟在另一个H1元素之后,那么这个例子的意图就是删除这个H1元素上面的空格。

清单 3-41 。 相邻兄弟组合子的绝佳用法

/* CSS snippet */
H1 + H1 {
    margin-top: -10px;
}

选择器组

我们已经看到了在类型、类、ID、属性等方面匹配的简单选择器。我们已经看到了使用组合子将简单的选择器串在一起形成层次结构。选择器还有一个非常重要的特性,那就是我们对它们进行分组的能力。希望用相同的样式属性来描述多个目标元素集是很常见的。例如,也许我们希望确保每个标题标签上方有 10 个像素的空间,无论它是h1h2还是其他。

这可以用单独的样式规则来描述,但是这是非常多余的,所以应该使用分组语法。分组就是简单地在选择器之间添加一个逗号。清单 3-42 展示了我们如何给所有的标题标签增加空间。

清单 3-42 。 一种样式规则,使用选择器链接来应用于五个级别的标题标签

/* CSS snippet */
h1, h2, h3, h4, h5 {
    margin-top: 10px;
}

重要的是要注意,当使用更复杂的选择器时,逗号表示选择链的完全重置。你可能会尝试类似于清单 3-43 中的代码,例如,对某个div下的所有标题标签应用相同的样式,但是结果并不是你想要的。因为逗号中断了选择链,所以h1将正确工作,但是h2h3h4选择器实际上将匹配文档中的每个h2h3h4

清单 3-43 。

/* CSS snippet */
#topDiv #childDiv h1, h2, h3, h4 {
    margin-top: 10px;
}

这个难题的解决方案是在链中的每个术语上包含完全限定的样式选择器。清单 3-44 展示了这个相当冗长但精确的解决方案。

清单 3-44 。 修正了选择器链,为每个术语添加了完整的层次结构

/* CSS snippet */
#topDiv #childDiv h1, #topDiv #childDiv h2, #topDiv #childDiv h3, #topDiv #childDiv h4 {
    Margin-top: 10px;
}

样式定义

记住,样式规则是由它的选择器和定义(也就是声明块)组成的。还要记住一个简单的概念,即在定义要修改的内容之前,必须先选择一些内容。我们已经详细讨论了如何选择你想要的东西,现在是时候实际做些什么了!

样式规则的定义非常容易理解,因为它只是一个键值对形式的样式属性集合。键和值总是用冒号(:)分隔,对之间用分号(;)分隔。

键是您将很快了解的许多 CSS 样式属性之一,值是该属性的有效值之一。

例如,颜色是 CSS 样式属性,红色是它的许多有效值之一。定义一个元素的文本颜色需要用一个选择器来定位该元素,然后为颜色属性键提供一个红色值。

清单 3-45 中的规则将使所有段落文本变成红色。

清单 3-45 。 将所有段落文本设置为红色

/* CSS snippet */
p {
    color: red;
}

你现在应该能认出选择器了。p是选择器。这是一个类型选择器,它将匹配文档中的每个段落标签。该定义由一个键值对组成。键是color,值是red

这是样式规则最简单的部分,但是它们也不会变得更复杂。选择器可能更长、更具体,这里多个样式属性对替换了单个属性对。

学习 CSS 主要涉及两件事:

  1. 学习如何使用选择器和
  2. 了解可供您使用的所有可能的样式属性

查看可用样式属性的最简单方法是在 Visual Studio 中使用 IntelliSense。当您在样式定义中调用智能感知时,您将看到所有可能的样式定义的完整列表(图 3-5 )。IntelliSense 不会根据哪些属性适用于您选择的元素类型来筛选列表。

9781430249832_Fig03-05.jpg

图 3-5 。应用于 CSS 样式属性的 Visual Studio 智能感知

有数百个属性,我将在后续章节中介绍其中的许多属性。现在,我只是想确保你理解一些使用它们的基本原则。

正如我所说的,定义一个样式属性非常简单,只需键入一个冒号(:),键入值,然后用分号(;).

清单 3-46 显示了在一个样式规则中定义的几个样式属性,该规则将应用于所有的p元素,并将指示其中的文本为蓝色和粗体。

清单 3-46 。 具有两个属性的样式规则

/* CSS snippet */
p {
    color: blue;
    font-weight: bold;
}

速记属性

您的样式规则可能很短,只有几个属性,也可能很长,有很多属性。这完全取决于需要对目标元素应用多少样式。

现在考虑下面的大尺寸样式规则,它将应用于所有的div元素,并指示它有一个 2px 宽、虚线和红色的边框。

div {
    color: blue;
    border-left-color: red;
    border-left-style: dashed;
    border-left-width: 2px;
    border-top-color: red;
    border-top-style: dashed;
    border-top-width: 2px;
    border-right-color: red;
    border-right-style: dashed;
    border-right-width: 2px;
    border-bottom-color: red;
    border-bottom-style: dashed;
    border-bottom-width: 2px;
}

令人生畏,不是吗?对于像在元素周围添加红色虚线边框这样简单的事情来说,这显然不是一种优雅的方式,这也是速记属性存在的原因。速记属性允许您一次定义多个样式属性。让我们利用简写属性可以节省的空间和时间重写最后一个例子。

div {
    color: blue;
    border: 2px dashed red;
}

那好多了。一处房产取代了 12 处!border属性是一个速记属性。它以空格分隔的特定顺序获取属性值列表,并将它们应用于更长的实际属性列表。

同样,Visual Studio 是您的朋友。当您输入一个简写属性时,您会得到一个工具提示,向您显示它所期望的以空格分隔的属性列表(图 3-6 )。

9781430249832_Fig03-06.jpg

图 3-6 。Visual Studio 的工具提示建议速记属性的值

看看这些常见的简写属性。。。

border:3px groove black;
font:bold 12px arial;
margin:4px 7px 2px 4px; /* sets the top, right, bottom, and left margins */
padding:10px 2px 7px 1px; /* sets the top, right, bottom, and left padding values */
background:url(image.png) no-repeat gray;

边距和填充属性(我们将在第三章中详细讨论)甚至有一些替代形式。

margin:4px 7px; /* sets the top/bottom margins to 4px, left/right margins to 7px */
padding:10px; /* sets padding to 10px on all sides */

属性值

有效属性值(冒号后面和分号前面的值)因样式属性而异,但它们都遵循一些基本规则。所有属性共享一个公共的有效值,即inherit。值inherit将指示属性应该从其父元素获取其值。

长度值必须是数字,后面紧跟下表中的一个标准 CSS 度量单位。

单位描述
em计算出的字体大小
Ex小写“x”的高度
Px像素,相对于观察设备
rem根元素的字体大小
vw视口宽度
vh视口高度
vm视口宽度或高度的较小值
ch零宽度(呈现字体中零字符的宽度)
in英寸
cm厘米
mm毫米
pt点数(1 点= 1/72 英寸)
pc十二点活字(1 点活字= 12 点)

除了这些测量单位之外,您还可以指定一个后跟百分号(%)的值来计算您相对于其容器的长度。例如,宽度为50%的表格单元格将(至少试图)占据表格宽度的一半。

CSS3 引入了一些函数,可以用来给单元添加一些额外的魅力。即使涉及不同的单元,函数也会为你做一些计算。下面的代码将div的宽度设置为比其父容器的全宽小 20 个像素,这在页面上放置对象时可能非常有用。

div {
    width:calc(100% - 20px);
}

min()max()将接受任意数量的参数,并分别返回较小的或最大的。要将左填充设置为 10%和 20 像素中较小的一个,您可以使用以下内容:

div {
    padding-left:min(10%,20px);
}

级联顺序、特异性和范围

使用 CSS 的最终目标是获得应用于文档元素的属性。因此,重要的是要考虑一些会影响哪些应用,哪些不应用的细节。

层叠

CSS 中的 C 代表级联,所以你可能会猜测它是这项技术的旗舰特性之一,你可能是对的。

级联是指将样式规则应用于目标元素的方式。一个样式规则可能只应用于一个元素,而被另一个更重要的样式规则覆盖。

您的浏览器(遵循 CSS 标准)决定这些规则中哪一个更重要的方式是一件相当复杂的事情。我会尽量保持简单,但你应该明白这里发生了什么,所以你不会发现自己抓耳挠腮,想知道为什么你的文本是绿色的,而你的意思是它是黑色的。

样式规则确实是按顺序应用的。但是那个顺序是什么?还记得将样式属性应用于页面元素的三种方法吗?内嵌样式、嵌入样式表和外部样式表。嵌入样式中的样式规则会覆盖外部样式表中的样式规则,内联属性会覆盖这两种规则。

查看清单 3-47 中的 HTML 页面和外部样式表,您能确定div中的Hello, World!文本是否要加粗吗?

***清单 3-47 。***CSS 样式规则的层叠性质

<!-- default.html -->
<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <link href="default.css" rel="stylesheet" />
    </head>
    <body>
        <div id="myDiv"style="font-weight:normal;" >
            Hello, World!
        </div>
    </body>
</html>

/* default.css */
#myDiv {
    font-weight: bold;
}

答案是不会大胆。外部样式表指示它应该是,但是内联样式用font-weight: normal属性覆盖了它。

如果您不确定哪些规则将被应用,哪些规则将被覆盖,请使用样式跟踪工具。大多数现代浏览器在开发人员工具中包含这样一个功能,当使用 Windows 8 应用程序时,Visual Studio 中也提供了同样的功能。

特异性

特殊性在这件事上也起了作用。特异性是一个奇特的词,用来描述计算机对你的选择器有多具体的最佳猜测,从而在与其他规则竞争时应该给它多少权重。如果两个样式规则以同一元素为目标,但其中一个以更具体的方式这样做,那么它被确定为具有更高的特异性,它获胜,并且应用该样式规则的属性而不是另一个。

例如,ID 选择器就非常具体。如果某个div元素是两个样式规则的目标,每个都试图给它一个不同的颜色边框,但是一个通过它的id引用它,另一个通过它的类型引用它,那么前者将获胜。下例中的div将会有一个红色的边框,尽管我们已经给了它一个蓝色的类。

<!-- HTML snippet -->
        <divid="myDiv" class="blue" >
            Hello, World!
        </div>

/* CSS snippet */
#myDiv {
    border: 1px solid red;
}

.blue {
    border: 1px solid blue;
}

为了更深入地了解 CSS 特异性,我推荐 David Powers 的书 Beginning CSS3

范围

当您学习 JavaScript 时,您将学习一种称为模块化模式的模式,这种模式旨在为某些 JavaScript 块提供范围,否则这些块将完全暴露给全局名称空间,从而暴露给应用程序中的所有其他代码。

CSS 没有这种东西。CSS 没有任何作用域!这意味着,如果在任何给定的 HTML 页面上引用了 100 个样式表,那么所有的 CSS 样式对于所有的页面都是可用的。

然而,Windows 8 应用程序往往遵循一种导航模式,即让用户停留在单个页面上(default.html),并加载用户导航到的页面的 HTML、CSS 和 JavaScript,而不是实际改变范围。这对开发者和用户来说都是一个非常好的实践。这实际上也是现代网站应用程序中一个非常流行的趋势,但是如果你在一个单页应用程序的一个页面上定义了一个 CSS 样式规则,你可能会不小心让这个规则影响到其他页面。因此,建议您在 CSS 样式的规则选择器前面加上 Windows 8 赋予所有页面片段的类,这只是页面的名称。

如果你在 Visual studio 的 Windows 8 项目中创建了一个名为orders.html的新项目,那么默认情况下你的页面的 HTML 将包含一个orders类的div。如果您在所有的选择器前面加上.orders和一个空格(记住,那是后代组合符),那么您的样式规则将只匹配页面中存在的元素。这是一个很好的实践。

媒体查询

CSS3 的前身 CSS2 有媒体类型。根据指定的媒体值,媒体类型允许应用不同的样式表。两个常见的媒体值是screenprint。这意味着当用户代理(通常是浏览器)将文档呈现到屏幕上时,开发人员可以指定一个应用于文档的样式表,而另一个样式表用于将文档呈现到打印机上。

CSS3 随着媒体查询的引入得到了很好的发展,极大地增加了功能。

有了媒体查询,我们不再需要引用完全不同的样式表,而是能够更精确地指定应用于各种媒体相关特征的 CSS 样式规则块。

媒体查询可以确定应该应用单个样式规则(比整个表单更细粒度),而不是仅仅确定在给定的情况下应该应用样式表(尽管这仍然是可能的)。

通过媒体查询,不仅可以区分各种媒体类型(如screenprint以及handheldprojectiontv),还可以区分方向(纵向和横向)以及各种大小、分辨率和纵横比。

将不同风格应用于不同媒体配置的能力对于 Windows 8 开发来说绝对至关重要。Windows 8 可以安装在大量的系统上;这些系统中的大多数都有不同的尺寸和分辨率屏幕——有些可以旋转——最重要的是,Windows 8 提供了捕捉应用程序的能力,将其设置为 320 像素宽,并将其放在屏幕上另一个应用程序的旁边。这引入了更多可能的渲染配置。

谢天谢地,媒体的询问让我们作为开发者的工作变得容易多了。

媒体查询以关键字@media开始,接着是媒体类型和一些特征,最后得到真或假的值。只有当类型和所有特征都匹配时,媒体查询才为真。

因此,有效的媒体查询语法如下所示:

@media type and feature1 and feature2 and featureN {
    styleRule1;
    styleRule2;
    styleRuleN;
}

类型的有效值为:screenprintbraillehandheldprintprojectionttytvembossedspeechall,特征的有效值为:widthheightdevice-widthdevice-heightorientationaspect-ratiodevice-aspect-ratiocolorcolor-indexmonochromeresolutionscangrid。在使用 Windows 8 应用时,-ms-view-state将会是你最好的朋友。这是您确定应用程序处于哪个视图状态的方法。它可以是全屏横向、全屏纵向、快照或填充(当一个应用程序被快照到你的应用程序旁边时)。

上面列举的特征值的子集可以以min-max-为前缀。例如,min-device-width: 800px的值将是有效的,并且有助于指定仅在所使用的设备至少 800 像素宽时才匹配的媒体查询。此外,如果设备支持 256 色或更少的颜色,max-color-index: 256的值将是有效的,并且将匹配。

可以通过用逗号分隔多个媒体查询来构建媒体查询列表。这只是在多种情况下应用同一套样式规则。在清单 3-49 中,当输出介质在屏幕或彩色打印机上时,颜色样式属性将应用于所有段落。

清单 3-49 。 针对屏幕和彩色打印机的媒体查询

/* CSS snippet */
@media screen, print and (color) {
    p {
        color: red;
    }
}

除了指定介质查询应适用的介质类型,您还可以指定介质查询应排除的介质类型。您可以使用以下命令进行媒体查询,该查询适用于除打印机之外的所有内容。。。

@media not print {
    p {
        color: red;
    }
}

这将在除打印之外的所有情况下应用颜色,在打印中可能希望节省彩色墨水。

如果你正在创建一个 Windows 8 应用程序,你肯定会想要处理至少两个视图状态——全屏景观和快照视图,如果没有其他的,媒体查询是可行的。

摘要

我们已经知道 CSS 的目的是用样式影响 HTML,而用样式影响 HTML 是一个双重过程,首先,选择一个或多个 HTML 元素,其次,定义应用于该选择的样式。

我们详细研究了选择过程——使用多种选择器类型和使用多种组合器类型将它们放在一起,这样我们的选择可以更加具体。

我们详细讨论了样式定义以及如何在样式定义中定义多个属性。我们还看到了速记属性的作用,使我们的样式属性更容易编写。

我们看到了样式规则如何级联、生效以及可能相互覆盖,我们还看到了如何使用媒体查询使样式规则仅在与设备、设备大小和视图状态相关的特定情况下生效。

接下来,我们将看看真实的、实时的样式属性,我们将从与样式文本相关的属性开始。