• CSS选择器的优先级(精讲版)

    几乎所有的 CSS 样式冲突、样式覆盖等问题都与 CSS 声明的优先级错位有关。因此,在详细阐述 CSS 选择器的优先级规则之前,我们先快速了解一下 CSS 全部的优先级规则。

    CSS 优先级规则概览

    CSS 优先级有着明显的不可逾越的等级制度,我将其划分为 0~5 这 6 个等级,其中前 4 个等级由 CSS 选择器决定,后 2 个等级由书写形式和特定语法决定。下面我将对这 6 个等级分别进行讲解。

    0 级

    通配选择器、选择符和逻辑组合伪类的优先级都是 0。

    通配选择器写作星号*。示例如下:

    * { color: #000; }

    选择符指+>~、空格和||

    逻辑组合伪类有:not():is():where等,这些伪类本身并不影响 CSS 优先级,影响优先级的是括号里面的选择器。例如:

    :not() {}

    需要注意的是,只有逻辑组合伪类的优先级是 0,其他伪类的优先级并不是这样的。

    1 级

    标签选择器的优先级是 1。示例如下:

    body { color: #333; }

    2 级

    类选择器、属性选择器和伪类的优先级是 2。示例如下:

    .foo { color: #666; }
    [foo] { color: #666; }
    :hover { color: #333; }

    3 级

    ID 选择器的优先级是 3。示例如下:

    #foo { color: #999; }

    4 级

    style属性内联样式的优先级是 4。示例如下:

    <span style="color: #ccc;">http://c.biancheng.net/</span>

    5级

    !important优先级是最高的,也就是 5。示例如下:

    .foo { color: #fff !important; }

    !important是顶级优先级,可以重置 JavaScript 设置的样式,唯一推荐使用的场景就是使 JavaScript 设置无效。例如:

    .foo[style*="color: #ccc"] {
      color: #fff !important;
    }

    对于其他场景,没有任何使用它的理由,切勿滥用。

    不难看出,CSS 选择器的优先级(0 级至 3 级)属于 CSS 优先级的一部分,也是最重要、最复杂的部分,学会 CSS 选择器的优先级等同于学会了完整的 CSS 优先级规则。

    CSS 选择器优先级的计算规则

    对于 CSS 选择器优先级的计算,业界流传甚广的是数值计数法。具体如下:每一段 CSS 语句的选择器都可以对应一个具体的数值,数值越大优先级越高,其中的 CSS 语句将被优先渲染。具体规则为:

    • 出现一个 0 级选择器,优先级数值+0
    • 出现一个 1 级选择器,优先级数值+1
    • 出现一个 2 级选择器,优先级数值+10
    • 出现一个 3 级选择器,优先级数值+100

    于是,有下表所示的计算结果。

    表1:选择器优先级计算值

    选择器

    计算值

    计算细则

    * {}

    0

    1 个 0 级通配选择器,优先级数值为 0

    dialog {}

    1

    1 个 1 级标签选择器,优先级数值为 1

    ul > li {}

    2

    2 个 1 级标签选择器,1 个 0 级选择符,优先级数值为 1+0+1

    li > ol + ol {}

    3

    3 个 1 级标签选择器,2 个 0 级选择符,优先级数值为 1+0+1+0+1

    .foo {}

    10

    1 个 2 级类名选择器,优先级数值为 10

    a:not([rel=nofollow]) {}

    11

    1 个 1 级标签选择器,1 个 0 级否定伪类,1 个 2 级属性选择器,优先级数值为 1+0+10

    a:hover {}

    11

    1 个 1 级标签选择器,1 个 2 级伪类,优先级数值为 1+10

    ol li.foo {}

    12

    1 个 2 级类名选择器,2 个 1 级标签选择器,1 个 0 级空格选择符,优先级数值为 1+0+1+10

    li.foo.bar {}

    21

    2 个 2 级类名选择器,1 个 1 级标签选择器,优先级数值为 10×2+1

    #foo {}

    100

    1 个 3 级 ID 选择器,优先级数值为 100

    #foo .bar p {}

    111

    1 个 3 级 ID 选择器,1 个 2 级类名选择器,1 个 1 级标签选择器,优先级数值为 100+10+11

    测试题

    趁热打铁,我出一个小题考考大家,<body> 元素的颜色是红色还是蓝色?

    HTML 代码:

    <html lang="zh-CN">
       <body class="foo">颜色是?</body>
    </html>

    CSS 代码:

    body.foo:not([dir]) { color: red; }
    html[lang] > .foo { color: blue; }

    我们先来计算一下各自的优先级数值。

    首先是body.foo:not([dir]),出现了 1 个标签选择器 body,1 个类名选择器.foo和 1 个否定伪类:not,以及属性选择器[dir],计算结果是 1+10+0+10,也就是 21。

    接下来是html[lang] > body.foo,出现了 1 个标签选择器 html,1 个属性选择器[lang]和 1 个类名选择器.foo,计算结果是 1+10+10,也就是 21。

    这两个选择器的计算值居然是一样的,那该怎么渲染呢?

    这就引出了另外一个重要的规则——“后来居上”。也就是说,当 CSS 选择器的优先级数值一样的时候,后渲染的选择器的优先级更高。因此,上题的最终颜色是蓝色(blue)。

    后渲染优先级更高的规则是相对于整个页面文档而言的,而不仅仅是在一个单独的 CSS 文件中。例如:

    <style>body { color: red; }</style>
    <link rel="stylesheet" href="a.css">
    <link rel="stylesheet" href="b.css">

    其中在 a.css 中有:

    body { color: yellow; }

    在 b.css 中有:

    body { color: blue; }

    此时,body 的颜色是蓝色,如下图所示,因为 blue 这段 CSS 语句在文档中是最后出现的。

    浏览器中body颜色的优先级
    图1:浏览器中 body 颜色的优先级

更多...

加载中...