Advertisement

30个你必须熟记的CSS选择器

by
This post is part of a series called CSS3 Mastery.
10 CSS3 Properties you Need to be Familiar With
Getting to Work with CSS3 Power Tools

Chinese (Simplified) (中文(简体)) translation by Yimin Zhou (you can also view the original English article)

你学会了基本的idclass类选择器和descendant后代选择器,然后就觉得完事了吗?如果这样,你就会错过许多灵活运用CSS的机会。虽然本文提到的许多选择器都属于CSS3,并且只能在现代的浏览器中使用,但学会这些是大有好处的。

1. *

* {
 margin: 0;
 padding: 0;
}

首先我们来认识一些简单的选择器,尤其针对初学者,然后再看其他高级的选择器。

星号可以用来定义页面的所有元素。许多开发者会使用这个技巧来把marginpadding都设为0。在快速开发测试中这种设置固然是好的,但我建议绝对不要在最终的产品代码中使用。因为会给浏览器增加大量不必要的负荷

星形*也可以用于子元素选择器(child selectors)。

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

这段代码会定义#container div所有子元素的样式。跟上面一样,如果可以尽量避免使用这个方法。

查看示例

兼容的浏览器

  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

2. #X

#container {
 width: 960px;
 margin: auto;
}

使用#号作为前缀可以选择该id的元素。这是最常见的用法,但使用id选择器时要谨慎。

问问自己:是否真的需要使用id来定义元素的样式?

id选择器比较局限,不能重用。如果可以的话,先尝试使用标签名称,HTML5的其中一个新元素,或使用伪类。

查看示例

兼容的浏览器

  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

3. .X

.error {
color: red;
}

这是class类选择器。idclass类选择器的区别是,类选择器可以定义多个元素。当你想定义一组元素的样式时可以使用class选择器。另外,可以使用id选择器来定义某一个特定的元素。

查看示例

兼容的浏览器

  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

4. X Y

li a {
text-decoration: none;
}

下一个最常见的选择器是descendant后代选择器。当你需要更精确地定位时,可以使用后代选择器。例如,假如说你只想选择无序列表里的链接,而不是所有的链接?这种情况下你就应该使用后代选择器。

经验分享 - 如果你的选择器看起来像X Y Z A B.error这样就错了。问问自己是否真的需要加入这么多负荷

查看示例

兼容的浏览器

  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

5. X

a { color: red; }
ul { margin-left: 0; }

假如你想定义页面里所有type标签类型一样的元素,而不使用id或者class呢?可以简单地使用元素选择器。比如选择所有的无序列表,可以用ul {}

查看示例

兼容的浏览器

  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

6. X:visited and X:link

a:link { color: red; }
a:visted { color: purple; }

我们使用:link伪类来定义所有还没点击的链接。

另外还有:visited伪类可以让我们给曾经点击过或者访问过的链接添加样式。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

7. X + Y

ul + p {
 color: red;
}

这是邻近元素选择器,只会选中紧接在另一个元素后的元素。这上面的示例中,只有每个ul后面的第一个段落是红色的。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

8. X > Y

div#container > ul {
border: 1px solid black;
}

X YX > Y的区别是后者只会选中直接后代。例如,看看下面的代码:

 <div id="container">
    <ul>
       <li> List Item
         <ul>
            <li> Child </li>
         </ul>
       </li>
       <li> List Item </li>
       <li> List Item </li>
       <li> List Item </li>
    </ul>
 </div>

#container > ul只会定义idcontainerdiv里的ul元素,而不会定义第一个li里的ul

因此,使用这种选择器的效果更佳。实际上,在JavaScript中尤其适用。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

9. X ~ Y

ul ~ p {
 color: red;
}

这种兄弟选择器跟X + Y很像,但没有那么严格。邻近选择器(ul + p)只会选择紧接在前一个元素后的元素,但兄弟选择器更广泛。比如,在上面的例子中,只要在ul后的p兄弟元素都会被选中。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

10. X[title]

a[title] {
 color: green;
}

这种是属性选择器,在上面的例子中,带有title属性的链接标签才会被匹配。没有title属性的标签不会受到影响。但如果想更具体地根据属性的值来选择,就继续往下看吧。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

11. X[href="foo"]

a[href="http://net.tutsplus.com"] {
color: #1f6053; /* nettuts green */
}

上面的代码定义了所以指向http://net.tutsplus.com的链接都是nettuts品牌的绿色。其他的链接不受影响。

注意我们把赋值放在引号里面,在JavaScript中选择元素的时候也要记住这么使用。尽可能地使用CSS3标准的选择器。

这种方法不错,但还是有点局限。万一链接也是指向Nettuts+,但路径是nettuts.com而不是完整的路径呢?这种情况下我们可以使用正则表达式(regular expression)。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

12. X[href*="nettuts"]

a[href*="tuts"] {
color: #1f6053; /* nettuts green */
}

这解决了上面的问题。星号表示赋值出现在属性的任意处。这样就定义了指向nettuts.comnet.tutsplus.com甚至tutsplus.com的链接。

要记住的是这种表达比较宽泛。假如链接包含tuts但指向了不是Envato旗下的网站呢?如果你想更精确,可以使用^&来匹配前缀和后缀。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

13. X[href^="http"]

a[href^="http"] {
 background: url(path/to/external/icon.png) no-repeat;
 padding-left: 10px;
}

你有想过有些网站是怎么在链接旁边加一个小图标指示这是外部链接吗?我相信你一定有见过这样的小图标,它们标示着链接会导向到另外的网站。

这非常容易做到。通常使用正则表达式来指定字符串的前缀。如果我们想定义所有href属性前缀为http的链接标签,我们可以使用上面代码的选择器。

可以看到我们没有使用http://,因为没有必要,而且这样不能匹配以https://开头的url。

接下来,比如说我们要定义所以指向图片的链接又要怎么办呢?这样可以匹配字符串的后缀

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

14. X[href$=".jpg"]

a[href$=".jpg"] {
 color: red;
}

再来,我们使用正则表达式符号$来表示字符串的后缀。在上面的例子中,我们将匹配所以指向图片或至少以.jpg结尾的url。要记住的是当然这些样式对gifpng是无效的。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

15. X[data-*="foo"]

a[data-filetype="image"] {
 color: red;
}

就像上面所说的,我们怎么匹配所有的图片,包括pngjpegjpggif?可以使用多个选择器。

a[href$=".jpg"],
a[href$=".jpeg"],
a[href$=".png"],
a[href$=".gif"] {
 color: red;
}

但这样很麻烦,也没有效率。另一种解决方法是使用自定义属性。比如在图片链接标签中添加data-filetype属性。

<a href="path/to/image.jpg" data-filetype="image"> Image Link </a>

这样,我们就可以使用属性选择器来定义链接的样式。

a[data-filetype="image"] {
 color: red;
}
查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

16. X[foo~="bar"]

 a[data-info~="external"] {
 color: red;
}

a[data-info~="image"] {
 border: 1px solid black;
}

这个技巧将会让小伙伴们对你刮目相看。并没有很多人知道这个技巧。波浪符号(~)可以让你定义取值带有空格的属性。

继续使用前面的自定义属性,创建data-info属性来匹配带有空格的取值。举个例子,这里我们匹配外部链接和图片链接。

"<a href="path/to/image.jpg" data-info="external image"> Click Me, Fool </a>

使用上面的代码,现在我们可以用波浪号的技巧来定义包含其中一个值的元素。

/* Target data-info attr that contains the value "external" */
a[data-info~="external"] {
 color: red;
}

/* And which contain the value "image" */
a[data-info~="image"] {
border: 1px solid black;
}

巧妙吧?

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

17. X:checked

input[type=radio]:checked {
 border: 1px solid black;
}

很简单,这个伪类可以用来定义选中(checked)的元素,比如单选按钮(radio)或多选按钮(checkbox)。

查看示例

兼容的浏览器

  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera

18. X:after

伪类beforeafter属于高级用法。几乎每一天都有人找到高效而有创意的新用法。这两个伪类可以在元素前面和后面添加内容。

许多人认识到这两个伪类是因为这是清除浮动的技巧。

.clearfix:after {
  content: "";
  display: block;
  clear: both;
  visibility: hidden;
  font-size: 0;
  height: 0;
  }

.clearfix { 
 *display: inline-block; 
 _height: 1%;
}

这个例子利用:after在元素后面添加间隔和清除浮动的元素。这是你值得拥有的高级技巧,尤其是当overflow: hidden;不管用的时候。

还有另一种创新的用法,查看我另一篇快速创建阴影的技巧

根据CSS3选择器规范,语法上你应该使用双冒号来::来指定伪类。然而,为了兼容多数浏览器,单冒号也被承认。实际上,在目前的情况下,使用单冒号的选择是明智的。

兼容的浏览器

  • IE8+
  • Firefox
  • Chrome
  • Safari
  • Opera

19. X:hover

div:hover {
background: #e3e3e3;
}

好吧,这个你一定懂。正式的叫法是用户交互伪类user action pseudo class。听起来有些费解,但实际上并非如此。想给用户鼠标划过的元素添加样式?这就派上用场了!

要记住的是在旧版的IE里,:hover只能用于链接标签。

最常见的用法是,比如,当鼠标划过链接,链接会出现下划线(border-bottom)。

a:hover {
 border-bottom: 1px solid black;
}

经验分享 - border-bottom: 1px solid black;text-decoration: underline;的效果更好。

兼容的浏览器

  • IE6+ (只能用于链接标签)
  • Firefox
  • Chrome
  • Safari
  • Opera

20. X:not(selector)

div:not(#container) {
 color: blue;
}

否定伪类非常有用。比如,我希望选中所有的div元素,除了一个idcontainer的div。上面的代码就很巧妙地做到了这一点。

或者,如果我想选中所有不是段落标签的元素,可以像下面这样,但不建议这样使用。

*:not(p) {
color: green;
}
查看示例

兼容的浏览器

  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera

21. X::pseudoElement

p::first-line {
 font-weight: bold;
 font-size: 1.2em;
}

我们可以使用伪元素(用::表示)来定义某些片段元素,比如第一行或第一个字母。要记住的是这只能用于块状(block)元素。

伪元素使用两个冒号::

下面匹配段落的第一个字母:

p::first-letter {
 float: left;
 font-size: 2em;
 font-weight: bold;
 font-family: cursive;
 padding-right: 2px;
}

上面的代码会先找到所有的段落,然后匹配元素的第一个字母。

这常用于创建类似报纸文章的样式。

匹配段落的第一行

p::first-line {
 font-weight: bold;
 font-size: 1.2em;
}

类似地,这里使用::first-line来定义元素的第一行的样式。

“为了兼容现有的样式标准,用户代理必须同时采纳CSS1和CSS2里使用单冒号来表示伪元素的标准(比如:first-line,:first-letter,:before和:after)。但新的伪元素不兼容这种特列。 - 资料来源

查看示例

兼容的浏览器

  • IE6+
  • Firefox
  • Chrome
  • Safari
  • Opera

22. X:nth-child(n)

li:nth-child(3) {
 color: red;
}

还记得以前我们不可以匹配一组序列元素里的某个元素吗?nth-child伪元素就能解决这个问题!

要注意的是nth-child指序列里的第n个元素,从1数起。如果你想匹配列表里的第二个元素,可以使用li:nth-child(2)

我们甚至可以使用这种方法来选择一系列的子元素。比如li:nth-child(4n)可以选择排在4的倍数的元素。

查看示例

兼容的浏览器

  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari

23. X:nth-last-child(n)

li:nth-last-child(2) {
 color: red;
}

假如你有一个无序列表里面有很多子元素,但你只想匹配第三到最后一个元素,那该怎么办?你可以使用伪类nth-last-child

这个技巧跟上面的一样,但是从集合的最后一个数起。

查看示例

兼容的浏览器

  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

24. X:nth-of-type(n)

ul:nth-of-type(3) {
 border: 1px solid black;
}

有时候你可能想通过元素的类型type来选择,而不是子元素child

假设有5个无序列表。如果你想定义第三个ul的样式,但又没有id来进行匹配,那么可以使用伪类nth-of-type(n)。在上面的代码中,只有第三个ul会有边框。

查看示例

兼容的浏览器

  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari

25. X:nth-last-of-type(n)

ul:nth-last-of-type(3) {
 border: 1px solid black;
}

当然,我们也可以使用nth-last-of-type来选择倒数第n个元素。

兼容的浏览器

  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

26. X:first-child

ul li:first-child {
 border-top: none;
}

这种伪类可以用于选中母元素的第一个子元素,常常用于去掉第一个或最后一个元素的边框。

例如,假设你有一个序列,每一行的元素都有上边框border-top和下边框border-bottom。这样的话第一个和最后一个元素看来起就没有那么整齐。

许多设计师就会通过给第一个和最后一个元素添加样式来解决,但实际上可以使用这里提到的伪类。

查看示例

兼容的浏览器

  • IE7+
  • Firefox
  • Chrome
  • Safari
  • Opera

27. X:last-child

ul > li:last-child {
 color: green;
}

last-childfirst-child的反面,可以匹配最后一个子元素。

示例

下面的例子展示了怎么使用这些伪类。先创建一个无序列表。

代码

<ul>
   <li> List Item </li>
   <li> List Item </li>
   <li> List Item </li>
</ul>

这是一个简单的列表。

CSS

ul {
 width: 200px;
 background: #292929;
 color: white;
 list-style: none;
 padding-left: 0;
}

li {
 padding: 10px;
 border-bottom: 1px solid black;
 border-top: 1px solid #3c3c3c;
}

这部分代码设置背景颜色,去掉浏览器给ul设置的padding,然后给li加上边框增加深度。

Styled List

给列表增加深度,可以给每个li添加比背景颜色深一点的下边框border-bottom。然后添加比背景颜色浅一点的上边框border-top

唯一的问题是,上图中无序列表的顶部和底部也会有边框,看起来有点奇怪。可以用伪类:first-child:last-child来解决。

li:first-child {
  border-top: none;
}

li:last-child {
 border-bottom: none;
}
Fixed

这样就好了。

查看示例

兼容的浏览器

  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera

对了,IE8也支持:first-child,但不支持:last-child

28. X:only-child

div p:only-child {
 color: red;
}

事实上你很少会用到only-child这个伪类,但是当你需要的时候是可以使用的。

only-child可以让你匹配唯一的子元素。例如,在上面的代码中,只有当div只有一个p子元素的时候段落字体才是红色的。

再看下面的代码。

<div><p> My paragraph here. </p></div>

<div>
 <p> Two paragraphs total. </p>
 <p> Two paragraphs total. </p>
</div>

在这种情况下,第二个div里面的段落不会被选中,只有第一个div的段落才被选中。只要母元素含有超过一个子元素,only-child伪类就会失效。

查看示例

兼容的浏览器

  • IE9+
  • Firefox
  • Chrome
  • Safari
  • Opera

29. X:only-of-type

li:only-of-type {
 font-weight: bold;
}

这个伪类有几种不同的用法。only-of-type会匹配母元素里没有邻近兄弟元素的子元素。例如,匹配所有只有一个列表元素的ul

首先想想要怎么做?你可以使用ul li,但这样会匹配所有无序列表的元素,这样only-of-type就是唯一的解决方法。

ul > li:only-of-type {
 font-weight: bold;
}
查看示例

兼容的浏览器

  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

30. X:first-of-type

first-of-type可以用来选择该类型的第一个元素。

练习

为了更好地理解,我们来做一个练习。拷贝下面的代码粘贴到你的代码编辑器里:

<div>
 <p> My paragraph here. </p>
 <ul>
    <li> List Item 1 </li>
    <li> List Item 2 </li>
 </ul>

 <ul>
    <li> List Item 3 </li>
    <li> List Item 4 </li>
 </ul>   
</div>

停下来想一下,怎么选中"List Item 2"。想到答案了(或者选择放弃)才继续看下面。

方案1

答案有很多种,首先是使用first-of-type

ul:first-of-type > li:nth-child(2) {
 font-weight: bold;
}

上面的代码中,首先找到页面中的第一个无序列表,然后找到它的直接后代,然后选择第二个元素。

方案2

Another option is to use the adjacent selector.

另一个选择是使用邻近选择器。

p + ul li:last-child {
 font-weight: bold;
}

这里先找到紧跟在p后面的ul,然后找到最后的元素。

方案3

我们还可以尝试使用不同的组合。

ul:first-of-type li:nth-last-child(1) {
 font-weight: bold;   
}

这里我们先找到页面的第一个ul,然后找到倒数第一个元素。

查看示例

兼容的浏览器

  • IE9+
  • Firefox 3.5+
  • Chrome
  • Safari
  • Opera

结语

如果你想兼容旧的浏览器,比如IE6,在使用这些新的选择器时需要更加注意。但是不要让旧浏览器妨碍你做新的尝试。可以参考浏览器兼容性列表。另外可以使用Dean Edward的E9.js

另外,当使用JavaScript类库的时候,比如jQuery,尽可能地使用原生的CSS3选择器。这样可以加快代码的运行速度,因为选择器引擎使用浏览器内置的解析器,速度更快。

感谢阅读,希望你能有所收获!

Advertisement