CSS选择器优先级

CSS优先级计算的快速回顾,最后附上一些应用知识的实例。

计算特殊性值的情况

选择器的特殊性值 由4个位构成,基础值用 0,0,0,0 表示,为了方便描述用 A,B,C,D 分别对应代表各个位:

能令A位增加的:行间样式

能令B位增加的:ID选择器

能令C位增加的:类选择器、属性选择器或伪类

能令D位增加的:元素和伪元素

通配选择器 * 对特殊性值没有贡献,也当做是经过加 0 计算了


例如:以下规则中选择器的特殊性分别是:

a{color: yellow;} /*特殊性值:0,0,0,1*/
div a{color: green;} /*特殊性值:0,0,0,2*/
.demo a{color: black;} /*特殊性值:0,0,1,1*/
.demo input[type="text"]{color: blue;} /*特殊性值:0,0,2,1*/
.demo *[type="text"]{color: grey;} /*特殊性值:0,0,2,0*/
#demo a{color: orange;} /*特殊性值:0,1,0,1*/
div#demo a{color: red;} /*特殊性值:0,1,0,2*/

验证结果参考demo

应对常见疑问:

  • 特殊性值不会进位
  • 假如特殊性值相同的两条规则应用到同一个元素,只有后声明的那条规则会生效
  • 由上文可得:外联样式优先级并不一定低于内联样式

外联样式指的是,样式放在.css文件里,然后html调用该文件

内联样式指的是,样式放在head标签的style标签里面

行内样式指的是,写在具体元素的style属性里面的样式

不计算特殊性值的情况

  • !important(权重) 优先于 任何需要计算的特殊性值,可以视它为1,0,0,0,0
  • 通配选择器 * 定义的规则 优先于 元素继承过来的规则

:not伪类例外

:not 否定伪类 在优先级计算中不会被看作是伪类,但是在计算选择器数量时还是会把其中的选择器当做普通选择器进行计数:

<style type="text/css">
div.outer p {
  color:red;
}
div:not(.outer) p {
  color: blue;
}
</style>
<div class="outer">
  <p>This is in the outer div.</p>
  <div class="inner">
    <p>This text is in the inner div.</p>
  </div>
</div>

结果:

“This is in the outer div.”红色;“This text is in the inner div.”蓝色。

解释:

选择器div.outer p 和选择器div:not(.outer) p的优先级是相同的。

:not被忽略掉了。

:not(.outer)中的.outer正常计数。

知识应用实例

a的四种状态实例

我们知道a标签有四种状态:链接访问前、链接访问后、鼠标滑过、激活,分别对应四种伪类:link、:visited、:hover、:active。

如果用这四个伪类对同一个元素设置同一个属性,那它们的声明顺序应该有一定要求,一般大家都遵循“爱恨原则LVHA”(LoVe HAte),为什么是这个顺序?不能是其它顺序吗?

当鼠标滑过a链接时,满足:link和:hover两个伪类,要改变a标签的颜色,就必须将:hover伪类在:link伪类后面声明;同理,当鼠标点击激活a链接时,同时满足:link、:hover、:active三种状态,要显示a标签激活时的样式(:active),必须将:active声明放到:link和:hover之后。

因此得出LVHA这个顺序。

这个顺序能不能变?可以,但也只有:link和:visited可以交换位置,因为一个链接要么访问过要么没访问过,不可能同时满足,也就不存在覆盖的问题。

对于:hover在IE6下只有a元素支持,:active只有IE6-7不支持,:focus在IE6-7下不被支持。 查阅文档

继承失效实例

代码示例:

<p>Hello,<span>CSS</span></p>

CSS代码:

* {
    color:red;
}
p {
    color:green;
}

结果:span标签内的文本颜色是红色,而不是绿色。

解释:

我们常用*来做CSS reset,这常见的问题是导致继承失效

继承的样式根本没有任何特殊性,而使用通配选择器*的声明具有0, 0, 0, 0特殊性。当二者冲突时,通配选择器胜出,导致继承失效。

自己写 CSS 时不要滥用 *,reset.css 也只是设置 margin, padding, box-sizing 等少数几个属性时才使用,这几个被重置的属性都不继承。

另外,不要用*设置font-family

进一步理解!important

使用!important不是一个好习惯,因为它改变了你样式表本来的级联规则,从而难以调试。

一些不成文规则

  • 不要在全站范围的css中使用!important.
  • 只在需要覆盖全站范围的css或是外部css(例如引用的ExtJs或是YUI)的时候才在指定的页面上使用!important
  • 不要在你的插件中使用!important
  • 永远都要优先考虑使用样式规则的优先级来解决问题而不是!important

取而代之,你可以:

更好的利用CSS的级联属性

更多的使用适合的选择器。比如在你需要选定的对象元素前加上更多的元素,使选择的范围缩小,你的选择器就变得更有针对性,从而提高优先级。

什么时候应该使用:

你的网站上有一个设定了全站样式的CSS文件,同时你(或是你同事)写了一些效果很差的行内样式(行内样式的优先级是最高的)。

在这种情况下,你就可以在你全局的CSS文件中写一些!important的样式来覆盖掉那些直接写在元素上的行内样式。

活生生的例子比如:有人在jQuery插件里写了糟糕的行内样式。


参考:css优先级计算规则–王美建

文章目录
  1. 1. 计算特殊性值的情况
    1. 1.1. 应对常见疑问:
  2. 2. 不计算特殊性值的情况
  3. 3. :not伪类例外
  4. 4. 知识应用实例
    1. 4.1. a的四种状态实例
    2. 4.2. 继承失效实例
      1. 4.2.1. 代码示例:
      2. 4.2.2. 解释:
  5. 5. 进一步理解!important
    1. 5.1. 一些不成文规则
    2. 5.2. 什么时候应该使用:
|