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

因为(对于某个元素的样式)只要用1次了!important,绝大多数的其他的样式选择器规则都因为优先级不够而失效。那么后期再想覆盖它的样式,就需要继续增加!important类型样式,样式表极其难维护。

什么时候应该使用:

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

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

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


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

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