尽管 CSS资源的数量越来越多，但是在 CSS邮件列表上仍然总是看到有人问同样的问题：如何 让设计居中？最好的圆角框技术是什么？如何创建三列布局？

如果你熟悉 CSS设计社区，那么寻找解决方案时无非就是回想一下某篇文章或某种技术曾在哪 个网站重点介绍过。但是，如果你是 CSS的初学者，或者没有时间阅读所有博客，那么这些信 息可能并不好找。

CSS 有些方面（比如定位模型和特殊性）比较晦涩，即使是有经验的 CSS开发人员也会遇到问 题。这是因为大多数 CSS开发人员都是靠自学的，他们从各种文章和别人的代码中学习经验， 而没有全面理解 CSS规范。这也不奇怪，因为 CSS规范本身十分复杂，常常还自相矛盾，它的 目标读者是浏览器厂商而不是网页开发人员。

此外，还得应付浏览器问题。浏览器的 bug和不一致性是现代 CSS开发人员面对的一个最大问 题。不幸的是，许多 bug都没有很好地记载，它们的修复方法基本上只是在开发人员之间口口 相传。你知道自己必须以某种方式做某件事，否则在某种浏览器中就会出问题。但是，你记不 住是在哪种浏览器中会出问题，也说不清为什么会出问题。

所以，我产生了写这么一本书的想法。这本书将最有用的 CSS技术汇总在一起，集中介绍实际 的浏览器问题，从而弥补人们欠缺的 CSS知识。本书会帮助你加快学习 CSS的进程，使你的编 码技术很快达到 CSS专家的水平。

读者对象

本书适合具有 HTML和 CSS基础知识的任何人 阅读。无论你是刚刚接触 CSS设计，还是已经 开发纯 CSS站点好几年了，书中都有适合你的内容。如果你已经使用 CSS一段时间了，但还没 有达到专家级水平，那么你能够从本书获得最大的收益。本书为你提供了各种实用的建议和示 例，可以帮助你精通现代 CSS设计。

本书结构

本书前 3章讨论基本的 CSS概念和最佳实践，帮助你轻松地入门。你将学习如何建立代码结构 和添加注释，了解 CSS定位模型的细节以及浮动和清理的工作原理。你也许已经掌握了其中的 许多内容，但是可能会发现自己有遗漏或理解不充分的地方。因此，前 3章是不错的 CSS入门 材料，也可以帮助你重温已经知道的知识。

介绍了基本知识之后，后面 5章讨论核心 CSS技术，比如操纵图像、链接和列表、设计表单和 数据表格，以及进行纯 CSS布局。每一章都由浅入深，最后讨论比较复杂的示例。在这几章中， 你将学习如何创建圆角框、带透明阴影的图像、标签页式导航条和交互式按钮。许多情况下， 我会先展示传统技术，然后说明如何用 CSS制作出同样的效果。如果你想研究本书中的示例， 可以从 www.cssmastery.com或 www.friendsofed.com下载所有示例代码 。

浏览器 bug是许多 CSS开发人员最头疼的问题，所以本书中的所有示例都着眼于创建跨浏览器 的技术。此外，本书还用一整章讨论 bug和 bug修复。在这一章中，你将全面学习 bug捕捉技 术，学会在 bug作乱之前就发现并消灭它，甚至还会学习是什么造成了 IE中许多看似毫无规 律的 CSS bug。

最后两章是真正的 "大餐"。Simon Collison和 Cameron Moll是两位最杰出的 CSS设计人员，他 们将本书讨论的各种技术组合成两个精彩的实例来研究。从而，你不但会学习这些技术的工作 原理，而且会看到如何将它们用在实际项目中。

本书可以从头到尾地阅读，也可以放在计算机旁边作为参考资料，随时查阅提示、技巧和技术， 决定权在你。

本书约定

本书使用了几个约定，需要注意。本书采用了以下术语。

"HTML"指 HTML和 XHTML这两种语言。

除非特别声明，"CSS"是指 CSS 2.1规范。

"Windows的 IE 6和更低版本"指 Windows的 IE 5.0～6.0。

"现代浏览器"是指最新版的 Firefox、Safari、Opera、IE 7以及 IE 7以上版本。

本书中的所有 HTML示例都应该嵌套在一个有效文档的<body>中，同时，CSS包含在外部样式 表中。偶尔为了尽量简短，HTML和 CSS放在了同一个代码示例中。但是在真实的文档中，这 些代码需要放在各自的位置上才能正常工作。

最后，对于包含重复数据的 HTML示例，我们不会列出每一行，而是适时地使用省略号表示部 分代码。

第 1章 基础知识 7 4.6 小结 82

1.1 设计代码的结构 7 第 5章 对链接应用样式 83

1.1.1 标记简史 8 5.1 简单的链接样式 83

1.1.2 文档类型、DOCTYPE切换和 5.2 让下划线更有趣 85 浏览器模式 18 5.2.1 简单的链接修饰 85

1.1.3 有效性验证 19 5.2.2 奇特的链接下划线 86

1.2 小结 21 5.3 已访问链接的样式 87 第 2章 为样式找到应用目标 22 5.4 为链接目标设置样式 87

2.1 常用的选择器 22 5.5 突出显示不同类型的链接 88

2.2 通用选择器 24 5.6 创建类似按钮的链接 91

2.3 高级选择器 24 5.6.1 简单的翻转 92

2.3.1 子选择器和相邻同胞选择器 24 5.6.2 图像翻转 93

2.3.2 属性选择器 26 5.6.4 CSS精灵 95

2.3.3 层叠和特殊性 29 5.6.5 用 CSS 3实现翻转 96

2.3.4 继承 33 5.7 纯 CSS工具提示 98

2.4 规划、组织和维护样式表 34 5.8 小结 100

2.4.1 对文档应用样式 34 第 6章对列表应用样式和创建导航条 101

2.4.2 样式指南 37 6.1 基本列表样式 101

2.5 小结 39 6.2 创建基本的垂直导航条 102 第 3章 可视化格式模型 38 6.3 在导航条中突出显示当前页面 105

3.1 盒模型概述 38 6.4 创建简单的水平导航条 106

3.1.1 IE和盒模型 40 6.5 创建图形化导航条 108

3.1.2 外边距叠加 41 6.6 简化的"滑动门"标签页式导航 110

3.2 定位概述 43 6.7 Suckerfish下拉菜单 112

3.2.1 视觉格式化模型 43 6.8 CSS图像映射 114

3.2.2 相对定位 44 6.9 远距离翻转 124

3.2.3 绝对定位 45 6.10 对于定义列表的简短说明 130

3.2.4 浮动 47 6.11 小结 131

3.3 小结 53 第 7章 对表单和数据表格应用样式 132 第 4章 背景图像效果 54 7.1 对数据表格应用样式 132

4.1 背景图像基础 54 7.1.1 表格特有的元素 134

4.2 圆角框 57 7.1.2 数据表格标记 135

4.2.1 固定宽度的圆角框 57 7.1.3 对表格应用样式 136

4.2.2 山顶角 62 7.1.4 添加视觉样式 137

4.3 投影 67 7.2 简单的表单布局 139

4.3.1 简单的 CSS投影 68 7.2.1 有用的表单元素 140

4.3.2 来自 Clagnut的投影方法 70 7.2.3 其他元素 142

4.4 不透明度 73 7.2.4 修饰 144

4.5 图像替换 78 7.3 复杂的表单布局 145

4.5.1 FIR 79 7.3.1 可访问的数据输入元素 146

4.5.2 Phark 80 7.3.2 多列复选框 147 4.5.3 sIFR 80 7.3.3 表单反馈 150

7.4 小结 152 第 10章 实例研究：Roma Italia 207 第 8章 布局 153 10.1 关于这个实例研究 207

8.1 计划布局 153 10.2 基础 209

8.2 设置基本结构 156 10.2.1 着眼于 HTML 5 210

8.3 基于浮动的布局 158 10.2.2 reset.css 211

8.3.1 两列的浮动布局 158 10.3 1080布局和网格 212

8.3.2 三列的浮动布局 161 10.4 高级 CSS 2和 CSS 3特性 215

8.4 固定宽度、流式和弹性布局 163 10.4.1 网站需要在每种浏览器中

8.4.1 流式布局 164 看起来完全一样吗 216

8.4.2 弹性布局 166 10.4.2 属性选择器 217

8.4.3 流式和弹性图像 168 10.4.3 box-shadow、RGBa

8.5 faux列 170 和 text-overflow 218

8.6 高度相等的列 173 10.5 字体链接和更好的 Web排版 221

8.7 CSS 3列 176 10.5.1 按以前的方式设置 font-size 221

8.8 CSS框架与 CSS系统 177 10.5.2 标点符号悬挂 222

8.9 小结 181 10.5.3 多栏文本布局 224 第 9章 bug和修复 bug 183 10.5.4 @font-face 225

9.1 捕捉 bug 183 10.5.5 Cufón，向@font-face

9.2 捕捉 bug的基本知识 189 发展的过渡手段 228

9.2.1 尽量在一开始就避免 bug 190 10.6 用 AJAX和 jQuery增加交互性 230

9.2.2 隔离问题 190 10.6.1 AJAX 230

9.2.3 创建基本测试案例 191 10.6.2 jQuery 231

9.2.4 修复问题，而不是修复症状 191 10.6.3 使用 AJAX和 jQuery实现搜索 232

9.2.5 请求帮助 192 10.7 小结 234

9.3 拥有布局 192 第 11章 实例研究：Climb the Mountains 235

9.3.1 什么是布局 192 11.1 关于这个实例研究 235

9.3.2 布局的效果 193 11.2 样式表的组织和约定 237

9.4 解决方法 195 11.2.1 screen.css 238

9.4.1 IE条件注释 195 11.2.2 reset 239

9.4.2 关于 hack和过滤器的一个 11.2.3 使用条件注释的 IE样式表 239 警告 196 11.3 网格灵活性 240

9.4.3 明智地使用 hack和过滤器 197 11.4 用 body类控制导航 241

9.4.4 应用 IE for Mac带通过滤器 197 11.4.1 突出显示当前页面 241

9.4.5 应用星号 HTML hack 198 11.4.2 控制 blockquote所处

9.4.6 应用子选择器 hack 199 的层 244

9.5 常见 bug及其修复方法 199 11.5 战略性地选择元素 245

9.5.1 双外边距浮动 bug 199 11.5.1 深层后代选择器 245

9.5.2 3像素文本偏移 bug 200 11.5.2 :first-child伪类 248

9.5.3 IE 6的重复字符 bug 201 11.5.3 相邻同胞选择器 249

9.5.4 IE 6的"藏猫猫"bug 202 11.6 透明度、阴影和圆角 250

9.5.5 相对容器中的绝对定位 203 11.6.1 我们的目标 251

9.5.6 停止对 IE的批评 204 11.6.2 说明图像覆盖和 RGBa透明度 252

9.6 分级浏览器支持 204 11.6.3 组合类 254

9.7 小结 206 11.6.4 border-radius 255

11.6.5 box-shadow 256 11.7.2 主海拔图 260

11.7 定位列表和显示内容 257 11.8 小结 266

11.7.1 圆角 259

序

在网页设计的精彩世界里，实现同一个目标有千百种方法，而且新的方法还在不断地出现。 对于特定的问题没有唯一正确的解决方法，丰富的选择使我们这些网页设计人员受益良多，同 时也困扰着我们。这些选择虽然能使网页设计变得生动有趣，但同时也会令人无所适从。本书 将帮助你减少麻烦，理清头绪。

Andy Budd 多年来一直在编写、设计和宣讲基于标准的网页设计，我们现在有幸在本书中 亲眼目睹他以简洁清晰的方式讲授最重要的 CSS技术。本书提供了一套网页设计人员不可或缺 的解决方案、技巧和建议。

有些图书中仅仅提出一种实现某一目标的正确方法，我很不喜欢这样的做法， Andy所做 的正好相反，他为各种任务提供了多种方法，如对链接应用样式，创建标签页式导航，使用节 省时间的 CSS 3解决方案，或创建固定、流式的、灵活的布局，这些都有多种途径加以实现， 书中还针对如何消除使用 CSS设计时出现的那些恼人的浏览器 bug给出了许多提示。掌握了常 见设计元素的这些时髦漂亮的设计方法，你就可以做出更明智的选择。

不只如此， Andy还邀请两位出色的设计人员将这些技术组合在一起，通过两个实例研究 向我们展示这些基本技术如何组合在一起。长期以来，我一直推崇 Cameron和 Simon的作品， 看了他们写的两个绝佳实例，讨论流式布局、无懈可击的布局和灵活多样的样式解决方案，真 的是受益匪浅。

好了，现在请开始深入研究并逐步消化这千百种设计方法，祝你早日成为精通 CSS的高手。

Dan Cederholm，经典著作 Web Standards Solutions一书的作者 第 1章 基础知识

人类天生就是一种好奇的动物，我们都很喜欢摆弄新鲜玩意儿。这不，最近我买了一台新 的 iMac，还没看说明书呢，自己就先把它鼓捣了一番。我们喜欢自己去琢磨，对新东西形成 自己的看法。我们会自己先胡乱摸索一阵子，发觉不对劲了，才会去查阅手册。

学习 CSS（层叠样式表）最好的一种方式是直接开始使用它。实际上，我认为大多数人学 习 Web编程的过程都是这样：先从博客上看到了一些出色的效果，于是通过查看源代码研究 它们是如何实现的，然后就在自己的个人网站上大胆尝试。人们几乎不会先去读完整的 CSS规 范，这些规范能把任何人送入梦乡。

修改别人的代码是很好的起步方法，但是如果不小心的话，就可能误解重要的概念，或者 给日后造成问题。这一点我很清楚，因为我犯过好几次了。本章将讲解一些基本的但常常被误 解的概念，并讨论如何让 HTML和 CSS保持清晰且结构良好。

在本章中，你将学习以下内容：

设计代码的结构；

有意义的文档的重要性；

命名约定；

什么时候使用 ID和类名；

微格式；

HTML和 CSS的不同版本；

文档类型、DOCTYPE切换和浏览器模式。

1.1 设计代码的结构

大多数人不关心建筑物的地基。但是，如果没有坚固的地基，建筑物的主体也就不会存在 了。虽然本书讨论的是高级的 CSS技术，但是如果没有结构良好且有效的 HTML文档，那么我 们要做的许多事情都是不可能实现的（至少实现起来非常困难）。

在本节中，你将明白为什么结构良好且有意义的 HTML文档在基于标准的 CSS开发中非常 重要，还将学习如何丰富文档的意义，从而让自己的开发工作更轻松。

1.1.1 标记简史

早期的 Web仅仅是一系列相互链接的研究文档，使用 HTML添加基本的格式和结构。但 是，随着万维网的流行，HTML开始用来表现页面。人们结合使用字体和粗体标签来创建所需 的视觉效果，而不只是用标题元素突出显示页面的标题。表格成了一种布局工具而不是显示数 据的方式，人们使用块引用（blockquote）来添加空白而不是表示引用。Web很快就含义不清， 成了字体和表格标签的大杂烩。Web设计者把这样的标记称为"标签汤"（见图 1-1）。

( 图 1-1)

网页变得越来越具表现力，代码却变得越来越难以理解和维护了。WYSIWYG（所见即所得） 编辑器让设计者可以摆脱这些复杂性，它宣称可以提供全新的图形布局环境。遗憾的是，这些 工具并没有使事情简化，反而添加了它们自己的复杂标记。使用 FrontPage或 Dreamweaver等 编辑器能够通过简单的鼠标操作构建复杂的表格布局，但是嵌套的表格和"分隔线 GIF"把代码 弄得非常混乱（见图 1-2）。更糟糕的是，这些布局极其脆弱，很容易被破坏。因为标记中有许 多无意义的代码，很容易意外删除错误的标签，整个布局就可能会崩溃。另外，由于代码的复 杂性，要找到 bug几乎是不可能的，这时从头编写页面往往比寻找 bug更容易。如果是大型网 站，情况会更复杂。因为网站的表现锁定到了各个页面，所以即使是最小的全站修改，也必须 进行细致的"搜索并替换"。我曾经由于轻率地执行"搜索并替换"，导致弄坏了不止一个网站。 因此，页面模板很快就不同步了，即使是简单的修改，也需要手工编辑网站上的每个页面。

表格本来不适合用来实现布局，所以 David Siegel发明了一种聪明的解决方法。为了避免 表格水平或垂直收缩，Siegel建议使用 1像素的透明 GIF。把这些隐藏的图像放在它们自己的 表格单元格中，然后垂直或水平伸缩它们，这样就可以人为地控制单元格的最小宽度，从而保 护布局不被破坏。这种图像也称为"shim GIF"，因为 Dreamweaver中使用这个文件名。在基于 表格的老式布局中常常会看到这种图像。好在这种做法已经过时了，现在代码中通常没有这些 混乱的表现性元素。

HTML 并没有被看做简单的标记语言，反而得到了复杂、混乱和容易出错的坏名声。因此， 许多人害怕直接编写代码，这导致人们过分依赖于可视化编辑器，造成整整一代设计者不知道 如何编写代码。

千禧年之际， Web设计业简直是一团糟，必须采取措施了。

( 图 1-2)

就在这种背景下，CSS出现了。有了 CSS，就可以控制页面的外观，并且将文档的表现部分与 内容分隔开。现在，只需在一个地方进行站点修改，修改就会贯彻到整个系统。可以去掉表现 标签（比如字体标签），而且可以使用 CSS而不是表格来控制布局。标记返朴归真，人们又开

始对底层代码感兴趣了。

文档又有意义了。浏览器的默认样式可以被覆盖，所以可以将某些内容标为标题，而不需要为 它指定大号的、加粗的、难看的字体。可以创建列表，而这些列表不一定要用一系列项目符号 来表示，可以使用没有关联样式的块引用。开发人员开始按照 HTML元素的原义使用它们，无 需管它们的外观（见图 1-3）。

（图 1-3）

1.意义的重要性

有意义的标记为开发人员提供了几个重要的好处。与表现性的页面相比，有意义的页面更 容易处理。例如，假设需要修改页面中的一个引用，如果这个引用加上了正确的标记，那么很 容易搜索代码，找到第一个块引用元素。但是，如果这个引用只是另一个段落元素标签，就很 难寻找了。再举一个更复杂但不太现实的例子，假设你需要在主页中添加一栏，只需把新内容 放在右边，然后在 CSS中更新宽度。要想在基于表格的布局中完成相同的任务，就需要在表格 中添加一列，修改 colspan设置，修改所有单元格的宽度，修改所有 shim GIF的宽度。实际上， 为了完成这个简单的修改，必须修改整个页面结构。

除了人之外，程序和其他设备也可以理解有意义的标记（也称为语义标记）。例如，搜索 引擎可以识别出标题（因为它被包围在 h1标签中）并予以重视。屏幕阅读器的用户可以依靠 标题进行页面导航。

对于本书来说，更重要的是，有意义的标记可以简便地将元素调整为你所需的样式。它在 文档中添加结构并且创建一个底层框架。可以直接设置元素的样式，而不需要添加其他标识符， 因此避免了不必要的代码膨胀。

HTML 包含丰富的有意义元素，比如： h1、h2等；

ul、ol和 dl；

strong和 em；

blockquote和 cite；

abbr、acronym和 code；

fieldset、legend和 label；

caption、thead、tbody和 tfoot。

因此，如果元素有恰当的含义，就应该使用。

几年来，在博客、邮件列表和开发人员论坛上，对于使用 CSS还是表格有许多争论。出现 这些争论常常是由于一部分开发人员习惯了基于表格的方法，他们不愿意学习新的技能。我可 以理解他们的想法，因为基于 CSS的布局最初看起来的确很难，尤其是当前的方法似乎仍然可 行时，他们更不愿意接受新东西。但是，CSS的好处非常多，包括代码更少、下载更快和更容 易维护等。大多数专业开发人员已经认识到 Web标准的好处，而且大多数组织都不愿意按老 方法做。因此，如果你仍然在使用基于表格的布局，会越来越难找到工作。好在这些老习惯正 在被摒弃，新一代开发人员已经很难忍受麻烦的表格布局了。

2. ID和类名

有意义的元素会提供很好的基础，但是可用元素并不全面。 HTML 4是作为简单的文档标 记语言创建的，而不是界面语言。因此，没有用于内容区域或导航栏等的专用元素。虽然可以 使用 XML创建自己的元素，但是由于它太复杂，这在目前还不太现实。

HTML 5 能为开发人员提供更丰富的元素，有望解决其中一部分问题。这包括 header、nav、 article、section和 footer等结构性元素，以及 data inputs和 menu元素等新的 UI特性。为了准 备迎接 HTML 5，许多开发人员已经开始采用这些名称作为 ID和类名的命名约定。

次优的解决方案是使用现有的元素，并且通过添加 ID或类名给它们赋予额外的意义。这 会在文档中添加额外的结构，并给样式提供有用的"钩子"（hook）。因此，可以建立一个简单 的链接列表，并且给它分配 ID nav，从而创建出定制的导航元素：

ID 用于标识页面上的特定元素（比如站点导航），而且必须是唯一的。ID也可以用来标识 持久的结构性元素，例如主导航或内容区域。ID还可以用来标识一次性元素，例如某个链接或 表单元素。

一个 ID名只能应用于页面上的一个元素，而同一个类名可以应用于页面上任意多个元素， 因此类的功能强大得多。类非常适合标识内容的类型或其他相似的条目。例如，假设有一个新 闻页面，其中包含多篇新闻，代码如下所示。

不必给每篇新闻分配不同的 ID，可以给所有新闻分配一个类名 news。

3.为元素命名

在分配 ID和类名时，一定要尽可能保持名称与表现方式无关。例如，如果希望所有表单 通知消息显示为红色的，可以给它们分配类名 red。只要页面上没有其他红色的元素，这就没 问题。但是，如果还希望让 4个必需的表单标签也显示为红色，就必须猜测这个类引用的是哪 种元素，这时情况就开始有些混乱了。想象一下，如果在整个网站上到处使用表现性元素，代 码会多么混乱。如果决定把表单通知由红色改为黄色，就更复杂了。在这种情况下，必须修改 所有类名，否则名为 red的元素就会显示为黄色。

因此，应该根据 "它们是什么"来为元素命名，而不应该根据"它们的外观如何"来命名。这 种方式会让代码更有意义，并且避免代码与设计不同步。对于前面的示例，不要给通知分配类 名 red，而是应该分配更有意义的名称，比如.warning或.notification（见图 1-4）。有意义的类 名的最大优点是可以在整个网站中重用它们。例如，还可以在其他类型的消息上使 用.notification类，可以根据它们在文档中的位置应用完全不同的样式。

在写类名和 ID名时，需要注意区分大小写，因为浏览器认为.andybudd和.andyBudd是不同的 类名。处理这个问题最好的方式是使用统一的命名约定。为了容易辨认，我总是采用完全小写 的类名和 ID，多个单词之间用连字符分隔。例如，andy-budd比 andyBudd清楚得多。

4. ID还是类

常常很难决定一个元素应该使用 ID还是类名。一般原则是，类应该应用于概念上相似的 元素，这些元素可以出现在同一页面上的多个位置，而 ID应该应用于不同的唯一的元素。但 是，究竟哪些元素是概念上相似的，哪些元素是唯一的？

例如，假设你的网站顶部包含主导航，在搜索结果页面的底部包含基于页面的导航，在页 脚上还有另一个导航。是给它们分配不同的 ID（比如 main-nav、page-nav和 footer-nav），还是 都给它们指定 nav类，然后根据它们在文档中的位置应用样式？我以前喜欢使用前一种方法， 因为它的针对性更强一点儿。但是，这有几个问题。如果我现在需要把搜索结果导航放在搜索 页面的顶部和底部，或者需要在页脚中有两级导航，那会怎么样？

如果使用大量 ID，很快就会难以找到唯一的名称，最终不得不创建非常长、非常复杂的命 名约定。因此，现在我比较喜欢使用类名。只有在目标元素非常独特，绝不会对网站上其他地 方别的东西使用这个名称时，才会使用 ID。换句话说，只有在绝对确定这个元素只会出现一次 的情况下，才应该使用 ID。如果你认为以后可能需要相似的元素，就使用类。保持命名约定通 用，并且使用类，就不会出现一长串 ID选择器都与非常相似的样式相关联的现象：

只需用一个普通的类替代它们：

由于类具有灵活性，所以它们是非常强大的。同时，它们也可能被过度使用或滥用。 CSS 新手常常在几乎所有东西上添加类，从而试图更精细地控制它们的样式。早期的 WYSIWYG编 辑器也倾向于在应用样式的每个地方都添加类。许多开发人员在使用编辑器生成的代码学习 CSS时继承了这个坏习惯。这种现象称为"多类症"（classitis），在某种程度上，这和使用基于表 格的布局一样糟糕，因为它在文档中添加了无意义的代码。

在前面的示例中，通过使用一个与新闻相关的类名，每个元素都被标识为新闻的一部分。 这使新闻标题和正文可以采用与页面其他部分不同的样式。但是，不需要用这么多类来区分各 个元素。可以将新闻条目放在一个部分中，并且加上类名 news，从而标识整个新闻条目。然 后，可以使用层叠（cascade）来识别新闻标题和文本。

只要你发现类名中出现了重复的单词，比如 news-head和 news-link或者 section-head和 section-foot，就应该考虑是否可以把这些元素分解成它们的组成部分。这会让代码更"组件化"， 会大大提高灵活性。

以这种方式删除不必要的类有助于简化代码，使页面更简洁。稍后，将简要讨论 CSS选择 器和为样式寻找目标。无论如何，这种对类名的过度依赖是完全不必要的。如果你发现自己添 加了许多类，那么这很可能意味着你的 HTML文档的结构有问题。

5. div和 span

有助于在文档中添加结构的一个元素是 div元素。许多人误以为 div元素没有语义。但是，div 实际上代表部分（division），它可以将文档分割为几个有意义的区域。所以，通过将主要内容 区域包围在 div中并分配 content类，就可以在文档中添加结构和意义。

为了将不必要的标记减到最少，应该只在没有现有元素能够实现区域分割的情况下使用 div元 素。例如，如果使用主导航列表，就不需要将它包围在 div中。

可以完全删除 div，直接在列表上应用类：

过度使用 div常常称为"多 div症"（divitus），这是代码结构不合理而且过分复杂的一个信 号。一些 CSS新手会尝试用 div重建自己原来的表格结构。但是，这只是用一套不必要的标签 替换了另一套不必要的标签。实际上，应该使用 div根据条目的意义或功能（而不是根据它们 的表现方式或布局）对相关条目进行分组。

可以用来对块级元素进行分组，而 span可以用来对行内元素进行分组或标识：div

尽管目标是让代码尽可能简洁且有意义，但是有时候为了以自己希望的方式显示页面，无 法避免添加额外的无语义的 div或 span。如果是这样，那也不必过分为此担心。我们正处在一 个过渡时期，CSS 3有望提供更强大的文档控制能力。而且，实际需要常常比理论出现得早。 关键是知道在什么时候必须进行折中，并且要有正确的原因进行折中。

6.微格式

由于 HTML中缺少相应的元素，很难突出显示人、地点或日期等类型的信息。为了解决这 个问题，有一组开发人员决定开发一套标准的命名约定和标记模式来表示这些数据。这些命名 约定基于 vCard和 iCalendar等现有的数据格式，现在称为微格式（microformat）。下面以我的 联系信息为例，代码采用 hCard格式。

微格式让我们可以以一种特定的方式标记数据，让其他程序和服务可以访问它。一些人编 写了脚本，可以提取出以 hCalendar格式标记的事件信息，并把它直接导入日历应用程序（见 图 1-5和图 1-6）。

(图 1-5)

还有一些人编写了插件，让 Firefox可以提取出以 hCard格式标记的联系信息，并通过蓝牙 发送到手机上（见图 1-7和图 1-8）。

(图 1-7)

当前有 9个正式的微格式，还有 14个格式草案。包括：

用于日期、日历和事件的 hCalendar

用于人和组织的 hCard

用于人之间的关系的 XFN

用于产品说明的 hProduct（草案）

用于原料和烹调步骤的 hRecipe（草案） 用于产品和事件审查的 hReview（草案） 用于博客帖子等片段式内容的 hAtom（草案）

许多大型网站已经支持微格式了。例如， Google Maps在地图搜索结果中使用 hCard格式 标记地址信息。类似地，Yahoo!的许多特性支持微格式，包括流行的 Flickr照片共享网站。Yahoo! 的 Kelkoo购物搜索引擎中使用 hListing格式，发布了 2600万条使用微格式的信息。在网站上 添加采用微格式的数据非常容易，所以我建议尽可能使用微格式。

这里只简要介绍了微格式可以实现的功能。如果需要了解更多信息，请阅读 John Allsopp 撰写的 Microformats: Empowering Your Mark-up for Web 2.0，还可以在 http://microformats.org 查阅正式规范。

7.不同的 HTML和 CSS版本

CSS 有多个版本，所以知道要使用哪个版本是很重要的。CSS 1在 1996年末成为推荐标准，其 中包含非常基本的属性，比如字体、颜色、外边距。CSS 2在 1998年发布，它添加了高级概念 （比如浮动和定位）以及高级的选择器（比如子选择器、相邻同胞选择器和通用选择器）。

万维网联盟（ W3C）的行动非常缓慢，所以尽管 CSS 3的开发工作在新千年到来之前就开始了， 但是距离最终的发布还有相当长的路要走。为提高开发和浏览器实现的速度，CSS 3被分割为 多个模块，这些模块可以独立发布和实现。CSS 3包含一些令人兴奋的新特性，包括一个高级 布局模块、全新的背景属性和一批新的选择器。其中一些模块原计划于 2009年下半年发布。 但是，目前还没什么进展，而且一些模块在发布前夕又回到了"最后公告"或"工作草案"状态， 所以很难确定实际发布会多少个模块。希望到 2011年会有许多模块成为正式的推荐标准。更 让人担心的是，一些模块还没有开始开发，其他模块好几年没有更新了。如此缓慢的开发进度 让人觉得 CSS 3似乎不可能全部完成了。

不过，尽管有一些拖延，还是有许多浏览器厂商已经实现了 CSS 3规范中比较有意思的一些特 性。因此，目前已经可以使用许多新的选择器了。

因为预期从 CSS 2到 CSS 3的发布之间时间会很长，2002年启动了 CSS 2.1的开发。这是 CSS 2 的修订版，它计划纠正一些错误，并且更精确地描述 CSS的浏览器实现。CSS 2.1正在逐渐完成， 因此我建议使用这个 CSS版本。

HTML 4.01 于 1999年末成为推荐标准，这是大多数人目前使用的 HTML版本。2000年 1月， W3C发布了 HTML 4.01的 XML版并命名为 XHTML 1.0。XHTML 1.0和 HTML 4.01之间的主要差 异是它遵守 XML编码约定。这意味着与常规的 HTML不同，所有 XHTML属性必须包含引号， 所有元素必须是封闭的。因此，以下代码在 HTML中是合法的，而在 XHTML中不合法：

在 XHTML 1.0中，必须写成下面这样：

XHTML 1.1 比 XHTML 1.0更接近 XML。这两种语言之间没有实际的差异。但是，有一个重 大的概念性差异。XHTML 1.0页面可以作为 HTML文档，而 XHTML 1.1页面是作为 XML发送给 浏览器的。这意味着，即使 XHTML 1.1页面只包含一个错误（比如未编码的&符号），Web浏 览器也不会显示页面。大多数网站开发人员显然不喜欢这样，所以 XHTML 1.1不受欢迎。

是把 XHTML 1.0页面作为 HTML提供，还是应该坚持使用 HTML 4.01？对于这个问题仍然 有争论。但是，显然不应该使用 XHTML 1.1，除非使用正确的 mime类型，而且能够容忍一个 错误导致整个页面无法显示。

HTML 5 相对较新，是一个不断变动的规范草案。但是，它的发展势头很强，一些流行的 浏览器已经开始着手支持它了。XHTML 2的开发非常缓慢而且过时了，让开发人员失去了信心。 因此，一批开发人员决定开发自己的规范，由此催生出了 HTML 5。这一行动非常成功，HTML 5已经成为正式的 W3C项目，而 XHTML 2的开发则停止了。

前面提到过， HTML 5的目标是建立一种现代的标记语言，可以更好地反映在 Web上发布 的信息类型。因此它引入了新的结构性元素，比如 header、nav、article、sections和 footer。 它还包含一批新的表单特性，可以大大简化 Web应用程序开发。

1.1.2 文档类型、DOCTYPE切换和浏览器模式

DTD （文档类型定义）是一组机器可读的规则，它们定义 XML或 HTML的特定版本中允许 有什么，不允许有什么。在解析网页时，浏览器将使用这些规则检查页面的有效性并且采取相 应的措施。浏览器通过分析页面的 DOCTYPE声明来了解要使用哪个 DTD，由此知道要使用 HTML 的哪个版本。

DOCTYPE声明是指 HTML文档开头处的一行或两行代码，它描述使用哪个 DTD。在下面的 示例中，要使用的 DTD是 XHTML 1.0 Strict的 DTD：

DOCTYPE通常-但不总是-包含指定的 DTD文件的 URL。例如，HTML 5就不需要 URL。浏 览器一般不读取这些文件，而是只识别常见的 DOCTYPE声明。

DOCTYPE 当前有两种风格，严格（strict）和过渡（transitional）。顾名思义，过渡 DOCTYPE 的目的是帮助开发人员从老版本迁移到新版本。因此，HTML 4.01和 XHTML 1.0的过渡版本仍 然允许使用已经废弃的元素，比如 font元素。但这些语言的严格版本禁止使用废弃的元素，从 而把内容和表现分隔开。

1.1.3 有效性验证

除了根据语义加标记之外， HTML文档还需要用有效的代码来编写。如果代码是无效的， 浏览器会尝试解释标记本身，有时候会产生错误的结果。更糟的是，如果发送具有正确的 MIME 类型的 XHTML文档，理解 XML的浏览器将不显示无效的页面。因为浏览器需要知道要使用什 么 DTD才能正确地处理页面，所以对页面进行有效性验证时要求有 DOCTYPE声明。

可以使用 W3C验证器（一个验证器 bookmarklet）或 Firefox Web Developer Extension等插 件检查 HTML是否是有效的。许多 HTML编辑器现在内置了验证器，还可以在计算机上本地安 装 W3C验证器。验证器会指出页面是否是有效的，如果是无效的页面，它还会指出原因是什 么（见图 1-9）。

( 图 1-9)

有效性验证很重要，因为它有助于找到代码中的 bug。因此，尽早和经常进行有效性验证 是个好习惯。但是，有效性验证太苛刻了，许多好页面由于很小的错误（比如&符号没有编码） 或者因为遗留的内容而无法通过有效性验证。所以，尽管有效性验证很重要，但是在实际中， 我们需要有一定的常识。

代码验证工具有很多种。可以访问 http://validator.w3.org/并且输入自己的 URL来对自己的

站点进行在线验证。但是，如果要经常进行验证（这是个好习惯），那么每次都输入自己的 URL 有点儿麻烦。我使用的是一个方便的验证器 bookmarklet（也称 favelet），这是一小段可以存储 在浏览器的书签或收藏夹中的 JavaScript。单击这个书签就会触发 JavaScript动作。对于验证器 bookmarklet，它通过 W3C验证器运行当前页面并显示结果。在 http://favelets.com上可以找到 这个验证器 bookmarklet和其他许多方便的 Web开发 bookmarklet。

如果使用的浏览器是 Firefox，那么可以下载和安装各种插件。在大量验证器插件中，我个 人喜欢的是 Web Developers Extension插件。除了可以验证 HTML和 CSS之外，它还可以执行许 多其他任务，比如描述各种 HTML元素、关闭样式表以及在浏览器中编辑样式。可以从 http://chrispederick.com/work/firefox/web-developer/下载 Firefox Web Developers Extension，这 是使用Firefox的CSS开发人员必须具备的插件。另一个出色的工具是Firefox Validator Extension， 可以从 http://users.skynet.be/mgueury/mozilla/下载它。

还有一个用于 IE 6和 IE 7的开发人员工具栏，可以从 http://tinyurl.com/7mnyh下载。尽管 它的特性不如 Firefox工具栏那么丰富，但是仍然非常有用。IE 8浏览器中直接构建了一套开发 工具，Safari 4也是如此。

DOCTYPE声明除了对有效性验证很重要之外，还被浏览器用于另一个用途。

1.浏览器模式

当浏览器厂商开始创建与标准兼容的浏览器时，他们希望确保向后兼容性。为了实现这一 点，他们创建了两种呈现模式：标准模式和混杂模式（quirks mode）。在标准模式中，浏览器 根据规范呈现页面；在混杂模式中，页面以一种比较宽松的向后兼容的方式显示。混杂模式通 常模拟老式浏览器（比如 Microsoft IE 4和 Netscape Navigator 4）的行为以防止老站点无法工作。

对于这两种模式之间的差异，最显著的一个例子与 Windows上 IE专有的盒模型有关。在 IE 6出现时，在标准模式中使用的是正确的盒模型，在混杂模式中使用的则是老式的专有盒模 型。为了维持对 IE 5和更低版本的向后兼容性，Opera 7和更高版本也在混杂模式中使用有缺 点的 IE盒模型。

呈现方面的其他差异比较小，而且是与特定浏览器相关的，包括对于十六进制颜色值不需 要#号、假设 CSS中没有指定单位的长度的单位是像素，以及在使用关键字时将字号增加一级。

Mozilla和 Safari还有第三种模式，称为"几乎标准的模式（almost standards mode）"，除 了在处理表格的方式上有一些细微的差异之外，这种模式与标准模式相同。

在 Firefox中，可以使用 Web Developer Extension查看页面的呈现模式。如果网站以标准 模式呈现，工具栏上会显示一个绿色的钩；若以混杂模式呈现，则显于红色的叉。IE 8中的开 发工具也显示浏览器使用的模式。

2. DOCTYPE切换

浏览器根据 DOCTYPE是否存在以及使用的哪种DTD来选择要使用的呈现方法。如果XHTML 文档包含形式完整的 DOCTYPE，那么它一般以标准模式呈现。对于 HTML 4.01文档，包含严格 DTD的 DOCTYPE常常导致页面以标准模式呈现。包含过渡 DTD和 URI的 DOCTYPE也导致页面 以标准模式呈现，但是有过渡 DTD而没有 URI会导致页面以混杂模式呈现。DOCTYPE不存在或 形式不正确会导致 HTML和 XHTML文档以混杂模式呈现。

根据 DOCTYPE是否存在选择呈现模式，被称为 DOCTYPE切换或 DOCTYPE侦测。并非所有 浏览器都采用这些规则，但是这些规则很好地说明了 DOCTYPE切换的工作方式。要了解更全 面的内容，可查阅网站 http://hsivonen.iki.fi/doctype/，这里的图表说明了不同浏览器如何根据 DOCTYPE声明来选择呈现方法。

DOCTYPE 切换是浏览器用来区分遗留文档和符合标准的文档的手段。无论是否编写了有效 的 CSS，如果选择了错误的 DOCTYPE，那么页面就将以混杂模式呈现，其行为就可能会有错误 或不可预测。因此，一定要在站点的每个页面上包含形式完整的 DOCTYPE声明，并且在使用 HTML时选择严格的 DTD。

许多 HTML编辑器会自动添加 DOCTYPE声明。如果创建 XHTML文档，一些老的编辑器还 可能在 DOCTYPE声明前面添加 XML声明：

XML 声明是 XML文件使用的可选声明，它定义使用的 XML版本和字符编码类型等设置。 不幸的是，如果 DOCTYPE声明不是页面上的第一个元素，那么 IE 6会自动切换到混杂模式。 这个问题在 IE 7中已经纠正了，但是除非要将页面用做 XML文档，否则最好避免使用 XML声 明。

1.2 小结

在本章中，你了解了语义性命名约定和有意义的标记如何让代码更容易阅读和维护，还了 解了 ID和类名之间的差异，以及各自适用的场合。我们还介绍了 CSS和 HTML可用的版本， 以及浏览器决定如何处理这些差异的方式。

在下一章中，我们将回顾一些基本的 CSS选择器，学习一些新的 CSS 3选择器，还要学习 特殊性和层叠，以及如何通过组织和计划样式表来简化维护。

第 2章 为样式找到应用目标

有效且结构良好的文档为你要应用的样式提供了一个框架。要想使用 CSS 将样式应用于特 定的 HTML 元素，需要想办法找到这个元素。在 CSS 中，执行这一任务的样式规则部分称为选 择器（selector ）。

在本章中，我们学习以下内容： 常用的选择器；

高级选择器；

新的 CSS 3 选择器；

特殊性和层叠的作用； 计划和维护样式表；

如何在代码中加注释。

2.1 常用的选择器

最常用的选择器类型是类型选择器和后代选择器。类型选择器用来寻找特定类型的元素， 比如段落或标题元素，只需指定希望应用样式的元素的名称。类型选择器有时候也称为元素选 择器或简单选择器。

后代选择器可用来寻找特定元素或元素组的后代。后代选择器由其他两个选择器之间的空 格表示。在这个示例中，只缩进是块引用的后代的段落元素，其他所有段落不受影响。

这两种选择器适合于应用那些应用范围广的一般性样式。要想寻找更特定的元素，可以使 用 ID 选择器和类选择器。顾名思义，这两种选择器用于寻找那些具有指定 ID 或类名的元素。 ID 选择器由一个#字符表示，类选择器由一个点号表示。下面示例中的第一条规则使简介段落 中的文本以粗体显示，第二条规则让日期显示为绿色：

前面提到过，许多 CSS 开发人员过度依赖类选择器和 ID 选择器。如果他们希望以一种方 式对主内容区域中的标题应用样式，而在第二个内容区域中采用另一种方式，那么他们很可能 创建两个类并且在每个标题上应用一个类。一种简单得多的方法是结合使用类型、后代、ID 和类这几种选择器：

这是一个非常简单明朗的示例。但是，让你吃惊的是，只使用前面讨论的 4 种选择器就可 以成功地找到许多元素。如果你发现自己在文档中添加了许多不必要的类，那么这可能是文档 结构不合理的一个警告信号。这时应该分析这些元素之间的差异。你常常会发现唯一的差异是 它们在页面上出现的位置。不要给这些元素指定不同的类，而应将一个类或 ID 应用于它们的 祖先，然后使用后代选择器定位它们。

伪类

有时候，我们需要根据文档结构之外的其他条件对元素应用样式，例如表单元素或链接的 状态。这要使用伪类选择器来完成。

:link 和:visited 称为链接伪类，只能应用于锚元素。:hover、:active 和:focus 称为动 态伪类，理论上可以应用于任何元素。大多数浏览器都支持这个功能。但是，IE 6 只注意应 用于锚链接的:active 和:hover 选择器，完全忽略:focus。IE 7 在任何元素上都支持:hover， 但是忽略:active 和:focus。

最后，值得指出的是：通过把伪类连接在一起，可以创建更复杂的行为，比如在已访问链 接和未访问链接上实现不同的鼠标悬停效果。

2.2 通用选择器

通用选择器可能是所有选择器中最强大却最少使用的。通用选择器的作用就像是通配符， 它匹配所有可用元素。与其他语言中的通配符一样，通用选择器由一个星号表示。通用选择器 一般用来对页面上的所有元素应用样式。例如，可以使用以下规则删除每个元素上默认的浏览 器内边距和外边距：

在与其他选择器结合使用时，通用选择器可以用来对某个元素的所有后代应用样式，或者 跳过一级后代。在本章稍后将看到这么做的实际效果

2.3 高级选择器

CSS 2.1 和 CSS 3 有其他许多有用的选择器。不过，虽然大多数现代浏览器支持这些高级选择 器，但是 IE 6 和更低版本不支持。好在在创建 CSS 时考虑到了向后兼容性。如果浏览器不理 解某个选择器，那么它会忽略整个规则。因此，可以在现代浏览器中应用样式和易用性方面的 改进，同时不必担心它在老式浏览器中造成问题。但是要记住，在对于站点功能或布局很重要 的任何元素上，都应该避免使用这些高级选择器。

2.3.1 子选择器和相邻同胞选择器

第一个高级选择器是子选择器。后代选择器选择一个元素的所有后代，而子选择器只选择元素 的直接后代，即子元素。在下面的示例中，外层列表中的列表项显示一个定制的图标，而嵌套 列表中的列表项不受影响（见图 2-1 ）：

图 2-1 子选择器指定列表的子

元素的样式，但是不影

响它的孙元素

IE 7 和更高版本都支持子选择器。但是，在 IE 7 中有一个小 bug，如果父元素和子元素 之间有 HTML 注释，就会出问题。

在 IE 6 和更低版本中，可以使用通用选择器模拟子选择器的效果。为此，先在所有后代 上应用你希望子元素具有的样式。然后，使用通用选择器覆盖子元素的后代上的样式。所以， 要实现与前面的子选择器示例相同的效果，可以这样做：

有时，你可能需要根据一个元素与另一个元素的相邻关系对它应用样式。相邻同胞选择器 可用于定位同一个父元素下某个元素之后的元素。可以使用相邻同胞选择器让顶级标题后面的 第一个段落显示为粗体、灰色，并且字号比后续段落略微大一点儿（见图 2-2 ）。

图 2-2 可以使用相邻同胞选择器对标题后面的

第一个段落应用样式，这样就不需要使用多余的类

与子选择器一样，如果在目标元素之间有注释，这在 IE 7 中也会出问题。

2.3.2 属性选择器

顾名思义，属性选择器可以根据某个属性是否存在或属性的值来寻找元素，因此能够实现 某些非常有意思和强大的效果。

例如，当鼠标悬停在具有 title 属性的元素上时，大多数浏览器会显示一个工具提示。可 以使用这种特性解释某些内容（比如首字母缩拼词和缩写词）的含义：

但是，如果不把鼠标悬停在这个元素上，那么没有任何迹象能够表明存在这一额外信息。 为了解决这个问题，可以使用属性选择器对具有 title 属性的 acronym 元素应用与其他元素不 同的样式--在下面的示例中，在它们下面加上点。还可以在鼠标悬停在这个元素上时将鼠标指 针改为问号，表示这个元素与众不同，从而提供更多的上下文相关信息。

除了根据某个属性是否存在对元素应用样式之外，还可以根据属性值应用样式。例如，使 用 rel 属性值 nofollow 链接的站点无法从 Google 获得评级收益（ranking benefit）。以下规 则在这种链接旁边显示一个图像，以此表示不推荐这个目标站点：

包括 IE 7 的现代浏览器都支持这些选择器。然而，由于 IE 6 不支持属性选择器，可以利 用它们对 IE 6 应用一种样式，对更符合标准的浏览器应用另一种样式。例如，Andy Clarke 利用这种技术为 IE 6 提供网站的黑白版本（见图 2-3），为其他所有浏览器提供彩色版本（见 图 2-4 ）。

一些属性可以有多个值，值之间用空格分隔。属性选择器允许根据属性值之一寻找元素。 例如，XFN 微格式允许在锚链接的 rel 属性中添加关键字来定义你与站点的关系。假设某个站 点属于我的同事，我就可以在博客上的链接中添加 co-worker 关键字来表示这一关系。然后可 以在这位同事的姓名旁边显示一个特殊的图标，以此表明我和这个人一起工作。

图 2-3 Andy Clarke 使用属性选择器和其他技术

为 IE 6 提供网站的黑白版本

图 2-4 更现代的浏览器显示的彩色版本

2.3.3 层叠和特殊性

即使在不太复杂的样式表中，要寻找同一元素可能有两个或更多规则。CSS 通过一个称为 层叠（cascade）的过程处理这种冲突。层叠给每个规则分配一个重要度。作者的样式表是由 站点开发者编写的，被认为是最重要的样式表。用户可以通过浏览器应用自己的样式，这些样 式表的重要度低一级。最后是浏览器或用户代理使用的默认样式表，它们的重要度是最低的， 所以你总是可以覆盖它们。为了让用户有更多的控制能力，可以通过将任何规则指定 为!important 来提高它的重要度，让它优先于任何规则，甚至优先于作者加上!important 标 志的规则。这种设置能够满足特殊的可访问性需求，例如如果用户有某种读写障碍，可以使用 中等对比度的用户样式表。

因此，层叠采用以下重要度次序。

标有!important 的用户样式。

标有!important 的作者样式。

作者样式。

用户样式。

浏览器/用户代理应用的样式。

然后，根据选择器的特殊性决定规则的次序。具有更特殊选择器的规则优先于具有一般选

择器的规则。如果两个规则的特殊性相同，那么后定义的规则优先。

1. 特殊性

为了计算规则的特殊性，给每种选择器都分配一个数字值。然后，将规则的每个选择器的 值加在一起，计算出规则的特殊性。可惜特殊性的计算不是以 10 为基数的，而是采用一个更 高的未指定的基数。这能确保非常特殊的选择器（比如 ID 选择器）不会被大量一般选择器（比 如类型选择器）所超越。但是，为了简化，如果在一个特定选择器中的选择器数量少于 10 个， 那么可以以 10 为基数计算特殊性。

选择器的特殊性分成 4 个成分等级：a、b、c 和 d。 如果样式是行内样式，那么 a = 1。

b 等于 ID 选择器的总数。

c 等于类、伪类和属性选择器的数量。

d 等于类型选择器和伪元素选择器的数量。

使用这些规则可以计算任何 CSS 选择器的特殊性。表 2-1 给出了一系列选择器以及相应的特殊 性。

表 2-1 特殊性示例

初看上去，上面的特殊性和更高的未指定的基数可能有点儿让人糊涂，所以再解释一下。基本 上，用 style 属性编写的规则总是比其他任何规则特殊。具有 ID 选择器的规则比没有 ID 选择 器的规则特殊，具有类选择器的规则比只有类型选择器的规则特殊。最后，如果两个规则的特 殊性相同，那么后定义的规则优先。

在修复 bug 时特殊性极其重要，因为你需要了解哪些规则优先及其原因。例如，假设有以下这 组规则，你认为两个标题会是什么颜色的？

令人吃惊的是，两个标题都是灰色的。第一个选择器由两个 ID 选择器组成，因此它具有 最高的特殊性。后面一些选择器看起来更复杂，但是因为它们只包含一个 ID，所以特殊性总 是低于第一个选择器。

如果你遇到了似乎没有起作用的 CSS 规则，很可能是出现了特殊性冲突。请在你的选择器 中添加它的一个父元素的 ID，从而提高它的特殊性。如果这能够解决问题，就说明样式表中 其他地方很可能有更特殊的规则，它覆盖了你的规则。如果是这种情况，你可能需要检查代码， 解决特殊性冲突，让代码尽可能简洁。

2. 在样式表中使用特殊性

在编写 CSS 时特殊性非常有用，因为它可以对一般元素应用一般样式，然后在更特殊的元 素上覆盖它们。例如，如果你希望站点上大多数文本是黑色的，但介绍说明文本是灰色的。可 以这样做：

对于小网站，这很好。但是，在大型站点上，你会发现例外情况越来越多。例如，你可能 希望新闻文章上的介绍文本是蓝色的，而主页上的介绍文本使用灰色背景。每当创建更特殊的 样式时，可能需要覆盖一些一般规则。这可能需要一些额外的代码。而且，因为元素可以从许 多地方获得样式，情况可能变得非常复杂。

为了避免过分混乱，我尽量保持一般性样式非常一般，特殊样式尽可能特殊，这样就不需 要覆盖特殊样式了。如果发现不得不多次覆盖一般样式，那么从更一般的规则中删除需要覆盖 的声明，并且将它显式地应用于需要它的每个元素，这样可能比较简单。

3. 在主体标签上添加类或 ID

一种有意思的特殊性用法是在主体（body）标签上应用类或 ID。这样做之后，就可以根 据页面或在站点范围内覆盖样式。例如，如果希望新的页面具有特殊的布局，那么可以在主页 的主体元素上添加一个类名，并且使用它覆盖样式：

有时候，在特殊页面上需要覆盖这些样式，比如在新闻存档页面上。在这种情况下，可以 在主体标签上添加 ID 来标识这个页面。

使用类标识页面类型，使用 ID 标识特定页面，就可以非常灵活地控制站点的设计和布局。 我很喜欢使用这种方法编写可维护的代码。

2.3.4 继承

人们常常将继承和层叠混为一谈。尽管它们初看上去有点儿相似，但是这两个概念实际上 是很不一样的。好在，继承是一个非常容易理解的概念。应用样式的元素的后代会继承样式的 某些属性，比如颜色和字号。例如，如果将主体元素的文本颜色设置为黑色，那么主体元素的 所有后代也显示黑色的文本。对于字号，也是这样的。如果将主体的字号设置为 1.4 em，那 么页面上的所有内容应该会继承这个字号。我说"应该会"是因为 Windows 的 IE 和 Netscape 在 继承表格中的字号方面有问题。为了解决这个问题，必须指定表格应该继承字号，或者在表格 上单独设置字号。

如果在主体上设置字号，你会注意到页面上的任何标题都没有采用这个样式。你可能会认 为标题没有继承文本字号。但是，实际上是浏览器的默认样式表设置了标题字号。直接应用于 元素的任何样式总会覆盖继承而来的样式。这是因为继承而来的样式的特殊性为空。

继承这一性质非常有用，因为它使开发人员不必在元素的每个后代上添加相同的样式。如 果打算设置的属性是继承而来的属性，那么也可以将它应用于父元素。可以编写：

但是下面的写法更简单：

正如恰当地使用层叠可以简化 CSS，恰当地使用继承也可以减少代码中选择器的数量和复 杂性。但是，如果大量元素继承各种样式，那么判断样式的来源就会变得困难。在 Firefox 中 可以使用 Firebug 查明样式的来源（图 2-5 ）。

图 2-5 Firebug是一个方便的 Firefox附加 组件，可以用它检查各个元素，查明它们 的样式的来源

2.4 规划、组织和维护样式表

站点越大、越复杂，图形越丰富，CSS 就越难管理。本节将讨论管理代码的方法，包括按 逻辑对样式进行分组以及通过添加注释使代码更容易阅读。

2.4.1 对文档应用样式

可以将样式放在 style 标签之间，从而直接在文档头上添加样式，但是，这不是对文档应 用样式的好方法。如果要创建使用相同样式的另一个页面，那么就不得不在新页面上复制 CSS。 如果以后要修改样式，那么就不得不在两处都进行修改。幸好 CSS 允许将所有样式放在一个或 多个外部样式表中。将外部样式表附加到网页上有两种方法。可以链接它们，也可以导入它们：

除了导入到 HTML文档之外，还可以从另一个样式表导入样式表。因此，你可以从 HTML 页面链接基本样式表，然后将复杂的样式表导入这个样式表：

把 CSS分割为多个样式表是一种常见的做法，我在本书的第 1版中也推荐过这种方法。 但是，最近的浏览器基准测试已经表明，导入样式表比链接样式表慢。

在使用多个 CSS文件时，还有两个与速度相关的问题。首先，多个文件会导致从服务器 发送更多数据包，这些数据包的数量（而不是内容）会影响下载时间。另外，浏览器只能从同 一个域同时下载数量有限的文件。对于老式的浏览器，这个限制常常只是两个文件，现代浏览 器把这个限制提到了 8个。因此，如果有 3个样式表，那么在老式浏览器中必须等下载完前两 个文件，才能开始下载第三个。由于这些原因，使用结构良好的单一 CSS文件可以显著提高 下载速度。

使用单一 CSS文件还能够把代码集中在一个地方。为了便于维护，我过去建议分割代码。 但是，总是很难判断某一声明是与站点的布局相关，还是与排版相关。它常常与两者都相关， 最终你会随意选择安置它的位置。分割代码还意味着必须打开多个样式表，经常要在文件之间 切换。最现代的 CSS编辑器中内置了代码折叠等特性，所以现在编辑单一文件非常容易。由 于这些原因，我现在倾向于使用单一 CSS文件而不是多个小文件。当然，应该根据站点的实 际情况做出决定，没有硬性规定。

在编写自己的样式表时，你可能很清楚它们的结构、曾经遇到的问题以及为什么采用某种 方式。但是，如果 6个月之后再来看这个样式表，你很可能已经忘了许多事情。另外，你可能 需要将自己的 CSS交给其他人去实现，或者其他开发人员以后需要编辑你的代码。因此，对 代码进行注释是一种好做法。

在 CSS中添加注释非常简单。CSS注释以/*开头，以*/结束。这种注释称为 C风格的注释， 因为 C语言中使用这种注释。注释可以是单行的，也可以是多行的，而且可以出现在代码中的 任何地方。

如果 CSS文件非常长，那么寻找特定的样式会很困难。一种改进方法是在每个注释头中 添加一个标志。这个标志仅仅是头文本前面的一个额外字符，一般不会出现在 CSS文件中。 搜索这个标志和注释头中的前几个字母，就可以立即找到要寻找的文件部分。所以，在下面的 示例中，搜索"@group typ"就会立即找到样式表中的版式部分：

OS X编辑器 CSS Edit就可使用这种格式创建一种简单但有效的样式表导航方法。

1.设计代码的结构

为了便于维护，最好把样式表划分为几大块。显然，常常把最一般的规则放在最前面。这 包括应用于 body标记的、应该由站点上所有元素继承的样式。接下来是可能需要的所有全局 reset样式，然后是链接、标题和其他元素。

完成一般样式之后，开始处理更特殊的样式和辅助样式。这些是在整个站点中使用的一般 类，包括表单和错误消息等方面。然后，处理布局和导航等结构性元素。

随着在样式表中的移动，我们在一层样式上构建另一层样式，处理的样式越来越特殊。处 理完页面结构元素之后，我们把注意力转到与特定页面相关的组件上。最后，在文档的底部处 理覆盖和例外情况。整个文档的结构像下面这样：

一般性样式

主体样式

reset样式

链接

标题

其他元素

辅助样式

表单

通知和错误

一致的条目

页面结构

标题、页脚和导航

布局

其他页面结构元素

页面组件

各个页面

覆盖

这里使用一种风格统一的大注释块分隔每个部分。

并非所有东西都能够自然地分成定义明确的块，这需要开发人员进行判断。请记住，代码 的分隔越细致、越合理，就越容易理解，而且能够更快地找到要寻找的规则。

因为我的许多 CSS文件可能具有相似的结构，所以我可以创建一个预先加上注释的 CSS 模板供所有项目使用，从而节省时间。还可以添加在所有站点上都使用的常用规则，形成某种 原型 CSS文件，这可以节省更多的时间。这样的话，在开始新项目时就不必总是重复以前的 工作。在本书的下载代码中可以找到一个原型 CSS文件示例。

2. 自我提示

对于复杂的大型项目，在 CSS文件中添加临时的注释常常对开发有帮助。这些注释可以 提醒你在启动前需要完成哪些工作，或者提醒你提供列宽度等常用值的查询表。

例如，如果设计中使用了许多种颜色，你可能常常需要到图形应用程序中查询十六进制值， 然后再返回到文本编辑器。这非常浪费时间，所以一些人认为需要 CSS变量。尽管这是一个 很有意思的主意，但是这会让 CSS更接近真正的编程语言，可能让非程序员畏惧它。因此， 我常常使用一种简单的方法。我在样式表的开头添加一个小的颜色查询表，这样就可以在开发 期间经常参考它。完成开发之后，我通常会删除它。

为了使注释更有意义，可以使用关键字来区分重要的注释。我使用 @todo来表示某些东西 需要在以后进行修改、修复或复查，用@bugfix表示代码或特定浏览器遇到的问题，用 @workaround表示并不完善的权宜之计：

用编程术语来说，这些关键字称为 gotcha，它们在以后的开发阶段中非常有帮助。实际上， 这些词汇都是 CSSDoc项目（http://cssdoc.net）的一部分，这个项目的目的是为样式表开发一 套标准的注释语法。

3. 删除注释和优化样式表

注释会使 CSS文件显著加大。因此，你可能需要从样式表中去掉一些注释。许多HTML/CSS 和文本编辑器都有"搜索并替换"选项，因此从代码中删除注释很容易。另外，还可以使用几种 在线 CSS优化器（比如 www.cssoptimiser.com/上提供的优化器）。优化器不但能够删除注释， 还可以删除空白，这可以从代码中去掉额外的字节。如果要从当前使用的样式表中删除注释， 一定要保留带注释的版本。管理这个过程的最好方法是创建一个部署脚本，当你让修改的内容 在生产环境中生效时，它自动地删除注释。但是，因为这是一种高级技术，可能只适用于很大 的复杂站点。

减小文件大小的最好方法可能是启用服务器端压缩。如果使用 Apache服务器，那么应该 安装 mod_gzip或 mod_deflate。所有现代浏览器都可以处理用 GZIP压缩的文件并进行即时解 压。这些 Apache模块探测浏览器是否能够处理这种文件，如果可以，就发送压缩的版本。服 务器端压缩能够将 HTML和 CSS文件减小大约 80%，这可以减少对带宽的占用，大大加快页 面的下载速度。如果无法使用这些 Apache模块，那么仍然可以按照 http://tinyurl.com/8w9rp上 的教程的说明对文件进行压缩。

2.4.2 样式指南

大多数 Web站点有多个开发人员，而大型站点甚至有多个团队负责处理站点的不同方面。 程序员、内容管理员和其他前端开发人员可能需要了解代码的元素和设计是如何工作的。因此， 建立样式指南是一种非常好的做法。

样式指南可以是一个文档、网页或小型站点，它们解释代码和站点的视觉设计是如何组合 在一起的。最基本的样式指南应该描述一般性设计原则，比如如何处理标题和其他排版元素， 网格结构的设计方式是什么，以及使用哪个调色板。好的样式指南还应该描述文章、新闻条目 和通知等重复元素的处理方法，决定它们应该如何实现和不应该如何实现。更详细的样式指南 甚至可以包含编码标准，比如使用的 XHTML/CSS版本、选择的可访问性级别、浏览器支持细 节和一般的编码最佳实践（见图 2-6）。

图 2-6 样式指南示例

样式指南是帮助维护或实现站点的好方法。通过制定一些简单的原则，可以确保站点的开 发以可控制的方式进行，同时防止样式随着时间的推移变得散乱。样式指南还非常有助于向新 职员或承包商介绍他们不熟悉、可能很复杂的系统。

糟糕的是，及时更新样式指南需要花费大量精力，所以它们常常很快就与当前的站点不同 步了。因此，我们更喜欢使用一种动态的样式指南形式，我们称之为"模式组合"（见图 2-7）。

图 2-7 WWF International站点的模式组合的一部分。实际

页面的长度大约是这里显示的 5 倍，包含这个站点上可能出现的每种排版和布局组合 模式组合是一个页面或一系列页面，它们使用当前的样式表显示站点上可能出现的每种样式排 列组合，从标题级别和文本样式直到特定的内容和布局类型。这些页面为后端和前端开发人员 提供极有价值的资源，让他们可以方便地构建页面组合。因为它们使用当前的样式表，所以也 可以用它们进行回归测试，检查对 CSS 的修改是否导致了问题。

2.5 小结

在本章中，我们回顾了常用的 CSS 2.1 选择器，学习了一些新的 CSS 3 选择器；详细了解 了特殊性的作用以及如何使用层叠控制 CSS 规则的结构，帮助规则找到目标；还学习了如何通 过合理的注释和样式表结构提高可维护性。

在下一章中，我们将学习 CSS 盒模型，讨论如何实现外边距叠加及其原因，以及浮动和定 位是如何工作的。