CSS3 是个好东西,但也很容易被她的变形(transform)和动画(其中许多特性因浏览器厂商而异)特性所迷惑,因而忘了那些已经被添加到标准规范中的最为基本的选择器。许多强大的新伪类选择器(最新的 W3C 规范中列出了 16 条)使得我们能够在新的标准范围内使用元素选择器。
在探讨这些新的 CSS3 伪类之前,先简要回顾追溯一下这些在 Web 应用中常常被误解的 CSS 选择器。
1. 伪类简史
在 1996 年,当 CSS1 的规范完成后,一些伪类选择器已被囊括在内,其中许多你几乎每天都在使用。例如:
:link
:visited
:hover
:active
这些状态都可以被应用到某个元素,通常是以 “a:伪类名”
的形式。令人难以置信的是,在 W3C 于 1997 年 12 月发布 HTML4 规范之前,这些伪类已经被极为广泛地使用了。
1.1 CSS2 来了
于是 CSS2 来了。其建议规范在两年之后的 1998 年 5 月发布。随之令人兴奋的是添加了 :first-child
和 :lang()
新伪类。
:lang
有许多种表示文档语言类型的方法,如果你使用 HTML5,很可能会直接在 DOCTYPE 声明之后放置 语句(指定本地语种)。当然,你也可以使用 :lang(en)
伪类来修饰页面元素,对于语言动态变化的情况,这将非常有用。
:first-child
您可能已经在文档中使用 :first-child
属性。它通常用于添加或删除列表中第一个元素的上边框。奇怪的是,却没有 :last-child
这样的伪类与之对应。于是不得等到 CSS3 规范的对这两个兄弟伪类的支持。
1.2 为何使用伪类?
伪类如此实用的原因在于它们允许动态地设置内容样式。比如上面的 <a>
例子,我们能够描述当用户与链接进行交互时,链接该如何呈现样式。正如我们看到的,新的伪类允许我们根据元素在文档中的位置或状态,动态地设置其样式。
16 个全新伪类已经成为 W3C 的 CSS 建议的一部分,它们被分成四组:结构伪类、UI 元素的状态伪类、一个目标(target)伪类和一个否定伪类。
W3C 是 CSS 之家
现在我们一起探究看看如何使用这 16 个新伪类选择器。我会使用和 W3C 相同的标识符来命名 CSS 类,比如 E
代表元素(element),n
表示数字(number),s
表示选择器(selector)。
1.3 示例代码
大部分新选择器都会给出参考示例,以便直观地看到代码呈现效果。这里会涉及一张适用于 iPhone 并且使用了 CSS3 伪类的表单。
请注意,这张表单中大部分样式可以使用 id 和类(class)选择器设定。即便如此,仍然可以使用新伪类针为这个表单锦上添花。点击这里查看页面示例
<form> <hgroup> <h1>Awesome Widgets</h1> <h2>All the cool kids have got one</h2> </hgroup> <fieldset id="email"> <legend>Where do we send your receipt?</legend> <label for="email">Email Address</label> <input type="email" name="email" placeholder="Email Address" /> </fieldset> <fieldset id="details"> <legend>Personal Details</legend> <select name="title" id="field_title"> <option value="" selected="selected">Title</option> <option value="Mr">Mr</option> <option value="Mrs">Mrs</option> <option value="Miss">Miss</option> </select> <label for="firstname">First Name</label> <input name="firstname" placeholder="First Name" /> <label for="initial">Initial</label> <input name="initial" placeholder="Initial" size="3" /> <label for="surname">Surname</label> <input name="surname" placeholder="Surname" /> </fieldset> <fieldset id="payment"> <legend>Payment Details</legend> <label for="cardname">Name on card</label> <input name="cardname" placeholder="Name on card" /> <label for"cardnumber">Card number</label> <input name="cardnumber" placeholder="Card number" /> <select name="cardType" id="field_cardType"> <option value="" selected="selected">Select Card Type</option> <option value="1">Visa</option> <option value="2">American Express</option> <option value="3">MasterCard</option> </select> <label for="cardExpiryMonth">Expiry Date</label> <select id="field_cardExpiryMonth" name="cardExpiryMonth"> <option selected="selected" value="mm">MM</option> <option value="01">01</option> <option value="02">02</option> <option value="03">03</option> <option value="04">04</option> <option value="05">05</option> <option value="06">06</option> <option value="07">07</option> <option value="08">08</option> <option value="09">09</option> <option value="10">10</option> <option value="11">11</option> <option value="12">12</option> </select> / <select id="field_cardExpiryYear" name="cardExpiryYear"> <option value="yyyy">YYYY</option> <option value="2011">11</option> <option value="2012">12</option> <option value="2013">13</option> <option value="2014">14</option> <option value="2015">15</option> <option value="2016">16</option> <option value="2017">17</option> <option value="2018">18</option> <option value="2019">19</option> </select> <label for"securitycode">Security code</label> <input name="securitycode" type="number" placeholder="Security code" size="3" /> <p>Would you like Insurance?</p> <input type="radio" name="Insurance" id="insuranceYes" /> <label for="insuranceYes">Yes Please!</label> <input type="radio" name="Insurance" id="insuranceNo" /> <label for="insuranceNo">No thanks</label> </fieldset> <fieldset id="submit"> <button type="submit" name="Submit" disabled>Here I come!</button> </fieldset> </form>
使用前和使用后的表单样式
2. 结构伪类
根据 W3C 规范,结构伪类用来做下面的事:
…允许选择位于文档树的额外信息,但不能用其他简单的选择器或组合选择器代替。
这意味着我们拥有了能根据选择器在文档中的所处位置,动态选择内容的选择器。那么让我们从文档本身开始,即 :root
伪类。
W3C 上的 Level 3 选择器
E:root
:root
伪类选择页面的根元素。十有八九根节点是 <html>
元素,例如:
:root { background-color: #fcfcfc; }
除了给 <html>
元素设定样式,这个伪类基本没什么价值,可能也就描述性稍强些:
html { background-color: #fcfcfc; }
回到那张 iPhone 表单,为其添加基本的文本和背景样式:
:root { color: #fff; text-shadow: 0 -1px 0 rgba(0,0,0,0.8); background: url(…/images/background.png) no-repeat #282826; }
E:nth-child(n)
:nth-child()
选择器可能需要一些实践才能完全理解。最简单的记忆方法是使用关键词“奇数或偶数”(odd
或 even
),因为在显示由行列组成的数据表格时,这将非常有用。例如,我们可以使用下列内容:
ul li:nth-child(odd) { background-color: #666; color: #fff; }
这将使无序列表中的每个奇数行高亮显示。您可能会发现在表格中使用这种技术非常方便。例如:
table tr:nth-child(even) { … }
:nth-child
选择器更明确灵活,因此,你可以选择列表的第三个元素,像这样:
li:nth-child(3) { … }
请注意 n 并不是从零开始,第一个元素是 :nth-child(1)
,第二个是 :nth-child(2)
,以此类推。
我们也可以利用一些简单的代数,使它变得更加精彩。考虑以下代码:
li:nth-child(2n) { … }
当我们以这种方式使用 n
,它代表对所有正整数,直到文档耗尽可选择的元素。在这种情况下,它会选择下列列表项:
- 未选择元素 (2 × 0)
- 第 2 个元素 (2 × 1)
- 第 4 个元素 (2 × 2)
- 第 6 个元素 (2 × 3)
- 第 8 个元素 (2 × 4)
- 等等…
这实际上和使用 :nth-child(even)
完全一致。因此我们混入点东西:
li:nth-child(5n) { … }
对应选择的节点元素:
- 未选择元素 (5 × 0)
- 第 5 个元素 (5 × 1)
- 第 10 个元素 (5 × 2)
- 第 15 个元素 (5 × 3)
- 第 20 个元素 (5 × 4)
- 等等…
对于长列表或表格而言,也许这将很有用,也可能完全无用。我们还可以在这一公式中执行数字加减法:
li:nth-child(4n + 1) { … }
对应选择的节点元素:
- 第 1 个元素 ((4 × 0) + 1)
- 第 5 个元素 ((4 × 1) + 1)
- 第 9 个元素 ((4 × 2) + 1)
- 第 13 个元素 ((4 × 3) + 1)
- 第 17 个元素 ((4 × 4) + 1)
- 等等…
这里 SitePoint 指出了一个怪癖的功能,如果你将 n
设置为负值,则可以像这样选择前 x
项。
li:nth-child(-n + x) { … }
如果你期望选择前 5 项,可以这样写:
li:nth-child(-n + 5) { … }
对应选择的节点元素:
- 第 5 个元素 (-0 + 5)
- 第 4 个元素 (-1 + 5)
- 第 3 个元素 (-2 + 5)
- 第 2 个元素 (-3 + 5)
- 第 1 个元素 (-4 + 5)
- 未选择元素 (-5 + 5)
- 未选择元素 (-6 + 5)
- 等等…
如果你想要根据热门程度来列数据条目,并予以突出显示,也就是说,前十项可能是很有用的。
WebDesign & Such 创建了 斑马样式示例,这应该是一个 :nth-child
的最佳实践。
使用 CSS3 设置表格的斑马样式
如果没有需要设置样式的表格,那么你可以 Webvisionary Awards 奖已经做的和使用:第n -孩子式交替其网站部分。这里的css:
如果你的表格都不需要设置样式,那么你可以像 Webvisionary Awards 那样,使用 :nth-child
设置网站区块的交替样式。CSS 代码如下:
section > section:nth-child(even) { background:rgba(255,255,255,.1) url("../images/hr-damaged2.png") 0 bottom no-repeat; }
其效果很细微,但它增加了一个陈旧浏览器不支持的细节。
Webvisionary Awards 上使用的 :nth-child 选择器
iPhone 表单案例
继续回到那张 iPhone 表单案例,这个案例中几乎很少地方可以使用 :nth-child
伪类,但值得注意的一点是,我们期望对前三个字段集的 label 标签隐藏,取而代之使用占位符(placeholder)文本替代。CSS 代码如下:
form:nth-child(-n+3) label { display: none; }
这里,我们寻找 <form>
元素的前三个子节点,然后选取 label 元素,可以使用 display:none;
来隐藏。
E:nth-last-child(n)
我们并不仅仅满足于 :nth-child()
伪类,W3C 也给我们提供了 :nth-last-child(n)
伪类。它和 :nth-child()
的表现非常相似,除了反向操作,从最后一个向开始计算的功能。
li:nth-last-child(1) { … }
上述将选择列表中的最后一个元素,而下面将选择倒数第二个元素:
li:nth-last-child(2) { … }
当然,你也可以使用其他规则:
li:nth-last-child(2n+1) { … }
但你可能更倾向于使用以下方法选择最后五个列表元素(以上面讨论的逻辑为基础):
li:nth-last-child(-n+5) { … }
如果这仍然没有太大的意义,Lea Verou 创造了一个有用的 CSS3 结构伪类选择器测试工具,值得一试。
CSS3 结构伪类选择器测试工具
iPhone 表单案例
在案例中,我们可以使用 :nth-last-child
来为“Card number”字段添加圆角。以下 CSS 代码可能过于具体,但至少提供了一个关联伪类的方法:
fieldset:nth-last-child(2) input:nth-last-of-type(3) { border-radius: 10px; }
我们首先抓住倒数第二个字段,选择其中倒数第三个字段(这个案例中,是“Card Number”字段)。然后,我们添加一个圆角效果(border-radius
)。
:nth-of-type(n)
现在我们将做得更加具体,只为特定类型的元素设定样式。例如,假设你想使得文章第一段具有较大的字体。CSS 代码如下:
article p:nth-of-type(1) { font-size: 1.5em; }
也许你要文章中的部分图片右对齐,另一部分左对齐。则可以使用关键字来控制:
article img:nth-of-type(odd) { float: right; } article img:nth-of-type(even) { float: left; }
通过 :nth-child()
和 :nth-last-child()
, 你可以使用代数表达式:
article p:nth-of-type(2n+2) { … } article p:nth-of-type(-n+1) { … }
值得记住的是如果需要获得这些指定的目标元素,使用描述性的 CSS 类名可能更合理。
Simon Foster 创建了一个 关于 45 张 RPM 唱片集的漂亮图表,并且使用 :nth-of-type
来为某些数据设置样式。以下是他的代码片段,CSS 中各流派类型都做了区分。
ul#genre li:nth-of-type(1) { width:32.9%; background:url(images/orangenoise.jpg); } ul#genre li:nth-of-type(2) { width:15.2%; background:url(images/bluenoise.jpg); } ul#genre li:nth-of-type(3) { width:13.1%; background:url(images/greennoise.jpg); }
网站上是这样呈现的:
For the Record 中的 :nth-of-type 选择器应用
iPhone 表单案例
比方说,我们希望偶数序号的输入框元素有底部圆角。可以用 CSS 实现这一点:
input:nth-of-type(even) { border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
该案例中,我们只期望应用到 “payment” 字段,因为个人信息含有三个文本输入框。处理方法有些棘手,要确保不会选择任何单选框。最终 CSS 代码:
#payment input:nth-of-type(even):not([type=radio]) { border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; border-bottom: 1px solid #999; margin-bottom: 10px; }
我们将稍后讲解 :not
伪类。
:nth-last-of-type(n)
现在来看看 :nth-last-of-type()
从选定元素的末尾开始,并且倒序工作。
要选择文章的最后一段,可以这样使用:
article p:nth-last-of-type(1) { … }
当文章不确定是否以段楼你可能会选择这个选择器来代替 :last-child
伪类。
:first-of-type 和 :last-of-type
如果 :nth-of-type()
和 :nth-last-of-type()
对你而言不太灵活,你可以使用更简单的选择器取而代之,例如:
article p:nth-of-type(1) { font-size: 1.5em; }
也可以这么搞:
article p:first-of-type { font-size: 1.5em; }
正如你所期望的那样,使用 :last-of-type
效果完全一样,只不过从后续元素开始查找而已。
iPhone 表单案例
我们可以在这张表单中结合使用 :first-of-type
和 :last-of-type
,特别是用于制作圆角。CSS 如下:
fieldset input:first-of-type:not([type=radio]) { border-top-left-radius: 10px; border-top-right-radius: 10px; } fieldset input:last-of-type:not([type=radio]) { border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
第一行 CSS 对所有具有 :first-of-type
伪类的 input 元素增加了圆角上边框,并且所在字段不是单选按钮。第二行对字段内的最后一个 input 元素增加圆角下边框。
:only-of-type
还有另一个选择器 :only-of-type()
。用于选择那些和它父元素中与自身同类型的元素。例如下面的代码:
p { font-size: 18px; }
以及:
p:only-of-type { font-size: 18px; }
第一个选择器将影响到页面中的所有 p 元素,第二个选择器只会影响它父亲节点下的所有 p 元素。
如果数据库查询只返回一个结果数据,为这个内容设置样式时,用 :only-of-type
可能会很方便。
Devsnippet 创建了一个 Demo,说明如何在多个图片中为单个图片定义样式。
Devsnippet’s 的 :only-of-type 案例
iPhone 表单案例
这张表单中,我们可以确保所有输入字段,无论在顶部还是底部,都有圆角效果,并且是该输入字段的唯一子节点。CSS 代码如下:
fieldset input:only-of-type { border-radius: 10px; }
:last-child
这是一个奇怪的地方::first-child
是 CSS2 的规范,但 :last-child
却在 CSS3 中才出现。也不需要过多语言解释,:last-child
用于选择父元素下的最后一个子节点。例如:
li { border-bottom: 1px solid #ccc; } li:last-child { border-bottom: none; }
这是一个从列表底部消除边框的有用方法,在 WordPress 小工具中可以经常看到这种应用。
Rachel Andrew 在他的 Cleaner Code With CSS3 Selectors 文章里谈论了 :last-child
和其他 CSS 伪类。他告诉我们如何使用这个伪类创建一份良好格式的图片画廊,而无需额外的 CSS 类。
Rachel Andrew 的 :last-child 伪类使用案例
:only-child
如果某个元素是它的父节点的唯一子节点,那么你可以使用 :only-child
选择它。不像 :only-of-type
伪类,并且和元素类型无关。例如:
li:only-child { … }
我们可以使用它来选择 <ul>
或 <ol>
中的单个列表项。
:empty
最后,结构伪类中,我们还有一个 :empty
。毫不奇怪,这个选择器只会选择那些没有子节点和文本节点的元素。如果从数据库中动态输入内容进行处理,这可能会非常有用。
#results:empty { background-color: #fcc; }
您可以使用该伪类来让用户注意搜索无结果的情况。
3. 目标伪类
:target
这是我最喜欢的伪类之一,因为它使我们可以基于 URL 对页面元素定义样式。如果 URL 有一个标识符(即带有一个 # 符号),那么 :target
伪类将为以该标识符为 id 属性的元素设置样式。比如以下的链接:
http://www.mangguo.org/how-to-use-css3-pseudo-classes#summary
id 属性为 summary
的区块现在可以这样设置样式:
:target { background-color: #fcc; }
对于已经被元素外部链接指向的页面元素来说,这是一个伟大的举措。你也可以使用它来高亮加了锚点的内容。
或许,最令人印象深刻的 :target
使用案例是 Corey Mwamba 的绿色滚动网站。他使用了一些富有创意的 CSS3 和 :target
伪类来创建动态的 Tab 导航效果。Demo 稿中包含了一些 CSS3 的巧妙用法,说明了伪类如何和其他 CSS 选择器结合使用。
Corey Mwamba 的绿色滚动网站
另外还有一个有趣的例子 Web Designer Notebook。利用了 :target
和 Webkit 动画来高亮目标 div 中的大块文本。Chris Coyier 还创建了一个基于 :target
伪类的 Tab 系统,发布在 CSS-Tricks 站点上。
iPhone 表单案例
这如我的 Demo 那样,我在顶部添加了一个导航栏,用于锚点定位到不同的表单区域。我们可以高亮任何区块:
:target { background-color: rgba(255,255,255,0.3); -webkit-border-radius: 10px;}
4. UI 元素状态伪类
:enabled 和 :disabled
UI 元素伪类包括 :checked
,:enabled
,:disabled
三个。可以允许根据元素状态来设定样式(通常是表单元素)。状态可以由用户设置(:checked
)或由开发者设置(:enabled
和:disabled
)。例如,我们可以使用下列内容:
input:enabled { background-color: #dfd; } input:disabled { background-color: #fdd; }
这将更有利于给予用户反馈,让他们知道可以可以填写、什么不能填写,你会经常看到这样的依赖 JavaScript 的动态特征。
iPhone 表单案例
为了实践说明 :disabled
,我已经禁用表单的“提交”按钮,并加入这行 CSS:
:disabled { color: #600; }
按钮文字变红了!
:checked
第三个伪类是 :checked
,用于处理元素的状态,如复选框或单选按钮。这对用户来说能给予非常有益的反馈,告诉他们选中了哪些。例如:
input[type=radio]:checked { font-weight: bold; }
iPhone 表单案例
当按钮按下时,我们可以用 CSS 来突出显示每个按钮旁边的文本:
input:checked + label { text-shadow: 0 0 6px #fff; }
我们首先选择任意已选中的 input 元素,然后查找包含目标文本的临近 <span>
元素,并使用简单的 text-shadow
属性来装饰。
5. 否定伪类
:not
这是我最喜欢的另一种选择器,因为它会选中除了指定元素之外的全部元素。例如:
:not(footer) { … }
这将选中页面上除了 footer 标签之外的任何元素,在网页上是不是一个页脚元素的一切。用于表单输入框时,可以实现单个输入框的突出显示。
input:not([type=submit]) { … } input:not(disabled) { … }
第一行选择除了 type 类型为 submit 的所有 input 元素。第二个选择所有不是 disabled 状态的 input 元素。
iPhone 表单案例
你已经切切实实看了 :not
选择器的作用。当与其他 CSS3 伪类混用时,他将变得更加强大。让我们来仔细看个例子:
fieldset input:not([type=radio]) { margin: 0; width: 290px; font-size: 18px; border-radius: 0; border-bottom: 0; border-color: #999; padding: 8px 10px;}
在这里,我们选择字段元素内不是单选按钮的 input 输入框。这在表单中是很常见的,因为文本输入框、下拉选择框、单选按钮、提交按钮往往是风格不一的。点此查看最终的表单效果
6. 旧瓶装新酒
让我们回到文章开头的 a:link
。 HTML5 为 <a>
元素带来了令人兴奋的变化,赋予 CSS3 伪类更多的功能。
<a>
元素现在可以嵌套块级元素,使整块的页面区块成为链接(只要这些部分不包含其他交互元素)。之前需要通过 JavaScript 来实现的,现在可以使用 <a>
嵌套方案轻松实现了。例如:
123
CSS 伪类的含义是,你可以随意为一个 <div>
设定样式,无论它是被悬停(a:hover
)活着被激活(a:active
),像这样:
a:hover #advert { background-color: #f7f7f7; }
减少对 JavaScript 代码的以来,并能适当增强代码语义总归是件好事。
7. 跨浏览器兼容性
你肯定会问,IE8(或更早)不支持任何形式的 CSS3 选择器,即使最新的 Chrome、Opera、Safari 和 Firefox 都支持良好。在你的血液沸腾前,请考虑以下解决方案。
Internet Explorer 9
你可能对微软这款最新的 IE9 浏览器并不非常知情。但事实上它相当不错。虽然我并不指望读者和我想法一致,值得记住的是,IE 是世界上最为广泛流行的浏览器,和 Windows Update 和微软全球性的营销活动下,希望在不久的将来可以看到 IE9 成为主流。这对于网页设计者是好事,对伪类选择器也是好事。但是 IE8 和他的祖先们怎么办?
Internet Explorer 9 来了
让我们的老朋友 JavaScript 来救援 CSS3 伪类吧。我特别喜欢 Keith Clark 的 Selectivizr。Keith 组建了一个适用于各种 JavaScript 类库的脚本,为早期版本的 IE 浏览器增加了 CSS3 伪类选择器功能。但是要注意,各种类库支持并不完全一致:如果你在 Mootools 上使用 Selectivizr,那么所有的伪类将可用,但如果你使用 jQuery,只有部分伪类可以正常工作。
Selectivizr
Keith recently 发布了一个 jQuery 插件来支持以下 CSS3 伪类:
:first-of-type
:last-of-type
:only-of-type
:nth-of-type
:nth-last-of-type
另外,也值得关注下 Dean Edwards 写的 ie7.js 脚本。这份脚本解决了一些 IE 相关问题,包括 CSS3 伪类。
因此,我们可以开始使用 CSS3 伪类了吗?
我想就这个问题的答案取决于你如何看待 JavaScript 这玩意儿。现实是伪类完全可以被 class 和 id 替代。另一个现实是,在设置复杂布局样式时,伪类非常有用并且理所而然、自然而然。如果你发现伪类提高了你的 CSS 可读性,并减少了 HTML 中的非语义 CSS 类,这也正式我建议拥抱 CSS3 伪类的原因。
你可以使用两个选择器和一个 class 名,但只是重复工作。这也意味着使用伪类并不是必须。如果你没有坚持原则,代码可能看起来像这样:
li:nth-of-type(3), li.third { … }
这种方法并不像使用伪类灵活,因为在内容变化时你需要同事改变 HTML 结构和 CSS 内容。
如果用户没有启用 JavaScript 会导致你陷入困境。许多网页设计师认为,功能(即 JavaScript)是和布局(即 CSS)不同的,所以你不应该依赖于 JavaScript 使 IE8 和早期浏览器支持伪类。
虽然我原则上统一,实际上我认为,相对于 99% 的用户提供最佳的经验和为剩余的 1% 用户做出让步,显然前者更好(假如你有大量无脚本的用户,那就另当别论)。
按照你的网站分析,并准备成为一个网页设计师不断提高自己的技能。更重要的是,尽力为广大用户提供最好的体验。
8. 最后的思考
IE8 对伪类支持的缺乏,很难不让人感到沮丧。可以说,浏览器以 JavaScript 方式计算和重新计算页面样式将对渲染速度造成影响,但因为所有其他主要浏览器现在支持这些选择器。令人沮丧的是,如果没有 JavaScript Hack 方案,我们的大多数用户无法从中受益。
但就像 Farnsworth 说的,Internet Explorer 9 的曙光将是一道分水岭,微软已确保其新的浏览器支持每个本文所讨论的选择器。
CSS3 伪类选择器不会大块占用你的样式表。他们是特有而充满活力的。而且更可能的是,至少在最初阶段,要补充性地优化,而不是实现一个整体的网页。也许你想丢弃列表最后一项的下边框,或向用户提供视觉反馈,因为他们在填写表格。CSS3 让这些都成为可能,并且会逐渐成为主流,我希望这将成为 Web 设计工具箱的一部分。
9. 相关参考
英文原稿:How To Use CSS3 Pseudo-Classes | Smashing Magazine
翻译整理:如何使用 CSS3 伪类 | 芒果小站
CSS3 :nth-child()伪类选择器:http://www.cnblogs.com/kiracn/archive/2009/12/17/1626742.html