权重

CSS 播客 - 003:权重

假设您正在使用以下 HTML 和 CSS

<button class="branding">Hello, Specificity!</button>
.branding {
  color: blue;
}

button {
  color: red;
}

这里有两条规则针对同一元素。每条规则都包含一个想要设置按钮颜色的声明:一条尝试将按钮着色为红色,另一条尝试将其着色为蓝色。哪个声明会应用于该元素?

理解 CSS 权重算法是理解 CSS 如何在竞争性声明之间做出决定的关键。

权重是层叠的不同阶段之一,在上一个关于层叠的模块中已经介绍过。

权重评分

来源中的每个选择器规则都会获得一个分数。您可以将权重视为总分,每种选择器类型都会为该分数赢得积分。权重最高的规则中的声明获胜。

在实际项目中,使用权重时的平衡之术是确保您期望应用的 CSS 规则确实应用,同时通常保持较低的分数以防止复杂性。权重应该只达到我们需要的程度,而不是追求尽可能最高的权重。将来,可能需要应用一些真正更重要的 CSS。如果您追求最高的权重,您将使这项工作变得困难。

权重不是十进制数字,而是一个由三个组件组成的三元组:ABC

  • A:类似 ID 的权重
  • B:类似类的权重
  • C:类似元素的权重

它通常使用 (A,B,C) 表示法表示。例如:(1,0,2)。另一种 A-B-C 表示法也很常用。

A diagram showingthe three components of specificity (A,B,C). For each component, the diagram shows what it represents and some example selectors that affect it.
一个图表,演示各种选择器影响权重的哪个组件。

比较权重

权重的比较是通过按顺序比较三个组件来完成的:A 值较大的权重更具体;如果两个 A 值相等,则 B 值较大的权重更具体;如果两个 B 值也相等,则 C 值较大的权重更具体;如果所有值都相等,则两个权重相等。

例如,(1,0,0) 被认为比 (0,4,3) 具有更高的权重,因为 (1,0,0) 中的 A 值(为 1)大于 (0,4,3) 中的 A 值(为 0)。

选择器影响权重

权重三元组中的每个部分都以值 0 开头,因此默认权重为 (0,0,0)。选择器的每个部分都会增加权重,具体取决于选择器的类型,会增加 ABC 的值。

通用选择器

通用选择器 (*) 不增加权重,使其值保持在初始权重 (0,0,0)

* {
  color: red;
}

元素或伪元素选择器

元素(类型)或 伪元素选择器增加类似元素的权重,这会将 C 组件递增 1

以下示例的总体权重为 (0,0,1)

类型选择器

div {
  color: red;
}

伪元素选择器

::selection {
  color: red;
}

类、伪类或属性选择器

伪类属性选择器增加类似类的权重,这会将 B 组件递增 1

以下示例的权重为 (0,1,0)

类选择器

.my-class {
  color: red;
}

伪类选择器

:hover {
  color: red;
}

属性选择器

[href='#'] {
  color: red;
}

ID 选择器

ID 选择器增加 类似 ID 的权重,这会将 A 组件递增 1,前提是您使用 ID 选择器 (#myID) 而不是属性选择器 ([id="myID"])。

在以下示例中,权重为 (1,0,0)

#myID {
  color: red;
}

其他选择器

CSS 有很多选择器。并非所有选择器都会增加权重。例如,:not() 伪类本身不会为权重计算增加任何内容。

但是,作为参数传入的选择器确实会被添加到权重计算中。

div:not(.my-class) {
  color: red;
}

此示例的权重为 (0,1,1),因为它有一个类型选择器 (div) 和一个 :not()内部的类。

检查您的理解

测试您对权重评分的了解

a[href="#"] 的权重是多少?

(0,0,1)
a 的值为 (0,0,1),但 [href="#"] 的值为 (0,1,0)
(0,1,0)
再试一次!a 的值为 (0,0,1),但 [href="#"] 的值为 (0,1,0)
(0,1,1)
a 的值为 (0,0,1)[href="#"] 的值为 (0,1,0),总权重为 (0,1,1)

不影响权重的因素

关于以下影响权重的因素,存在一些常见的误解。

内联样式属性

直接应用于元素 style 属性的 CSS 不影响权重,因为它是在权重之前评估的 层叠中的不同步骤。

<div style="color: red"></div>

为了从样式表内部覆盖此声明,您必须求助于在 层叠的早期步骤中获得声明的胜利。

例如,您可以向其添加 !important,使其成为 Authored !important 来源的一部分。

!important 声明

CSS 声明末尾的 !important 不影响权重,而是将声明放在不同的来源中,即Authored !important

在以下示例中,.my-class 的权重与 !important 声明获胜无关。

.my-class {
  color: red !important;
  color: white;
}

当两个声明都是 !important 时,权重再次发挥作用,因为层叠的来源步骤尚无法确定获胜者。

.branding {
  color: blue !important;
}

button {
  color: red !important;
}

上下文中的权重

当使用复杂或复合选择器时,该选择器的每个部分都会加起来形成权重。考虑以下示例 HTML

<a class="my-class another-class" href="#">A link</a>

此链接上有两个类。以下 CSS 中的规则的权重为 (0,0,1)

a {
  color: red;
}

如果您引用选择器中的一个类,则现在它的权重为 (0,1,1)

a.my-class {
  color: green;
}

将另一个类添加到选择器,现在它的权重为 (0,2,1)

a.my-class.another-class {
  color: rebeccapurple;
}

href 属性添加到选择器,现在它的权重为 (0,3,1)

a.my-class.another-class[href] {
  color: goldenrod;
}

最后,向所有这些添加 :hover 伪类,选择器最终的权重为 (0,4,1)

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

检查您的理解

测试您对权重评分的了解

以下哪个选择器的权重为 (0,2,1)

article > section
元素增加类似元素的权重(“C”组件)。选择器中有 2 个元素,使此选择器的权重为 (0,0,2)
article.card.dark
元素增加类似元素的权重(“C”组件),类增加类似类的权重(“B”组件)。使用 2 个类和 1 个元素,这使此选择器的权重为 (0,2,1)
article:hover a[href]
元素增加类似元素的权重(“C”组件),伪类和属性增加类似类的权重(“B”组件)。有 2 个元素选择器(2 × (0,0,1)),一个属性选择器(值为 (0,0,1))和一个类选择器(值为 (0,0,1))。这使此选择器的总权重为 (0,2,2)

实际增加权重

假设您有一些 CSS 看起来像这样

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

HTML 看起来像这样

<button class="my-button" onclick="alert('hello')">Click me</button>

按钮具有灰色背景,因为第二个选择器的权重为 (0,1,1)。这是因为它有一个类型选择器 (button),其值为 (0,0,1),以及一个属性选择器 ([onclick]),其值为 (0,1,0)

前一个规则——.my-button——等于 (0,1,0),因为它有一个类选择器,其权重低于 (0,1,1)

如果您想提升此规则的权重,您可以像这样重复类选择器

.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

现在,按钮将具有蓝色背景,因为新选择器获得了 (0,2,0) 的权重

权重相同时,会回退到层叠的下一步

现在让我们继续使用按钮示例,并将 CSS 切换到此

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

按钮具有灰色背景,因为两个选择器都具有相同的权重,即 (0,1,0)

如果您切换源顺序中的规则,则按钮将变为蓝色。

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

这是因为两个选择器都具有相同的权重。在这种情况下,层叠会回退到出现顺序步骤

资源