实际的工作中,当有多个选择器作用在一个元素上时,哪个规则最终会应用到元素上?其实这是通过层叠机制来控制的,这也和样式继承(元素从其父元素那里获得属性值)有关。样式的优先级就是这样的一个机制,它包括!important,专用性和源代码次序(CSS定义的位置及先后顺序)。
1.1 重要性
在CSS中,有一个特别的语法可以让一条规则总是优先于其他规则:!important。把它加在属性值的后面可以使这条声明有无比强大的力量。
关于!important此处不详细介绍,它利弊同在,在工作中公共样式表万万不能用!important。
知道 !important存在是很有用的,这样当你在别人的代码中遇到它时,你就知道它是什么了。但是!我们建议你千万不要使用它,除非你绝对必须使用它。您可能不得不使用它的一种情况是,当您在CMS中工作时,您不能编辑核心的CSS模块,并且您确实想要重写一种不能以其他方式覆盖的样式。 但是,如果你能避免的话,不要使用它。由于 !important 改变了层叠正常工作的方式,因此调试CSS问题,尤其是在大型样式表中,会变得非常困难。
相互冲突的声明将按以下顺序适用,后一种将覆盖先前的声明:
- 在用户代理样式表的声明 (例如:浏览器在没有其他声明的默认样式).
- 用户样式表中的普通声明(由用户设置的自定义样式)。
- 作者样式表中的普通声明(这是我们设置的样式,Web开发人员)。
- 作者样式表中的重要声明
- 用户样式表中的重要声明
1.2 专用性
专用性基本上是衡量选择器的具体程度的一种方法(它能匹配多少元素)。
元素选择器具有很低的专用性;类选择器具有更高的专用性,所以将战胜元素选择器;ID选择器有甚至更高的专用性,所以将战胜类选择器;战胜ID选择器的唯一方法是使用 !important。
一个选择器具有的专用性的量是用四种不同的值(或组件)来衡量的,它们可以被认为是千位,百位,十位和个位(在四个列中的四个简单数字):
千位 |
如果声明是在style属性中该列加1分(这样的声明没有选择器,所以它们的专用性总是1000。)否则为0。 |
百位 |
在整个选择器中每包含一个ID选择器就在该列中加1分。 |
十位 |
在整个选择器中每包含一个类选择器、属性选择器、或者伪类就在该列中加1分。 |
个位 |
在整个选择器中每包含一个元素选择器或伪元素就在该列中加1分。 |
下表显示了几个示例。理解专用性的含义和计算过程。
选择器 |
千位 |
百位 |
十位 |
个位 |
合计值 |
h1 |
0 |
0 |
0 |
1 |
0001 |
#important |
0 |
1 |
0 |
0 |
0100 |
h1 + p::first-letter |
0 |
0 |
0 |
2 |
0003 |
li > a[href*="en-US"] > .inline-warning |
0 |
0 |
2 |
2 |
0022 |
#important div > div > a:hover, 在一个元素的 <style> 属性里 |
1 |
1 |
1 |
3 |
1113 |
下面通过一个例子来展示专用性值。
HTML
<div id="outer" class="container"> <div id="inner" class="container"> <ul> <li class="nav"><a href="#">One</a></li> <li class="nav"><a href="#">Two</a></li> </ul> </div> </div> |
CSS
/* specificity: 0101 */ #outer a { background-color: red; } /* specificity: 0201 */ #outer #inner a { background-color: blue; } /* specificity: 0104 */ #outer div ul li a { color: yellow; } /* specificity: 0113 */ #outer div ul .nav a { color: white; } /* specificity: 0024 */ div div li:nth-child(2) a:hover { border: 10px solid black; } /* specificity: 0023 */ div li:nth-child(2) a:hover { border: 10px dashed black; } /* specificity: 0033 */ div div .nav:nth-child(2) a:hover { border: 10px double black; } a { display: inline-block; line-height: 40px; font-size: 20px; text-decoration: none; text-align: center; 200px; margin-bottom: 10px; } ul { padding: 0; } li { list-style-type: none; } |
1.3 源代码次序
如果多个相互竞争的选择器具有相同的重要性和专用性,后面的规则将战胜先前的规则。
比如页面中有HTML代码:<div class="a b c">nDos</div>,先后有样式.c { color:yellow; } .b { color:blue; } .a { color:red; }。那么nDos应该显示什么颜色?这里有一点混淆的地方,那就是元素中class出现的次序,这个次序毫无意义,nDos最终显示红色,按照样式出现的先后次序来竞争。假如更改样式出现的次序,比如:.c { color:yellow; } .a { color:red; } .b { color:blue; },那么nDos将显示蓝色。
1.4 关于层叠
在考虑所有这些层叠理论和什么样式优先于其他样式被应用时,你应该记住的一件事是,所有这些都发生在属性级别上(属性覆盖其他属性),但你不会让整个规则凌驾于其他规则之上。
当多个CSS规则匹配相同的元素时,它们都被应用到该元素中。只有在这之后,任何相互冲突的属性才会被评估,以确定哪种风格会战胜其他类型。
1.5 继承
CSS中某些元素若在父元素设置了之后,子元素就算不设置,也会默认获得该属性。比如color和font-family属性,若父元素设置{ color:red },则其子元素若不修改该属性,则文本将默认显示为红色。继承并不难理解,上面介绍了两个可以被继承的属性,那么padding属性能否继承呢?显然不能,原因不再赘述。
关于默认可以被继承的属性列表,以及不能继承的属性列表,请参见另外一篇博文CSS中能够以及不能够被继承的属性。
控制继承
CSS为处理继承提供了三种特殊的通用属性值:
inherit: 该值将应用到选定元素的属性值设置为与其父元素一样。
initial :该值将应用到选定元素的属性值设置为与浏览器默认样式表中该元素设置的值一样。如果浏览器默认样式表中没有设置值,并且该属性是自然继承的,那么该属性值就被设置为 inherit。
unset :该值将属性重置为其自然值,即如果属性是自然继承的,那么它就表现得像 inherit,否则就是表现得像 initial。
注意: initial 和 unset 不被IE支持。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSS继承</title> <style> body { color: green; } .inherit a { color: inherit; } .initial a { color: initial } .unset a { color: unset; } </style> </head> <body> <ul> <li>默认的 <a href="#">link</a> 颜色</li> <li class="inherit">inherit的 <a href="#">link</a> 颜色</li> <li class="initial">initial的 <a href="#">link</a> 颜色</li> <li class="unset">unset的 <a href="#">link</a> 颜色</li> </ul> </body> </html> |
我们首先设置<body> 的color为绿色。
由于color属性是自然继承的,所有的body子元素都会有相同的绿色。需要注意的是默认情况下浏览器设置链接的颜色为蓝色,而不是自然继承color属性,因此在我们列表中的第一个链接是蓝色的。
第二个规则设置一个类 inherit 的元素内的链接,并从父类继承它的颜色。在这种情况下, 意思是说链接继承了父元素<li>的颜色,默认情况下<li>的颜色来自于它的父元素 <ul> , 最后<ul> 继承自 <body>元素,而<body>的color 根据第一条规则设置成了绿色。
第三个规则选择了在元素上使用类 initial 的任意链接然后设置他们的颜色为 initial 。通常, initial 的值被浏览器设置成了黑色,因此该链接被设置成了黑色。
最后一个规则选择了在元素上使用类 unset 的所有链接然后设置它们的颜色为 unset ——即我们不设置值。因为color属性是一个自然继承的属性,它实际上就像把值设置成 inherit 一样。结果是,该链接被设置成了与body一样的颜色——绿色。