CSS 播客 - 003:权重
假设您正在使用以下 HTML 和 CSS
<button class="branding">Hello, Specificity!</button>
.branding {
color: blue;
}
button {
color: red;
}
这里有两条规则针对同一元素。每条规则都包含一个想要设置按钮颜色的声明:一条尝试将按钮着色为红色,另一条尝试将其着色为蓝色。哪个声明会应用于该元素?
理解 CSS 权重算法是理解 CSS 如何在竞争性声明之间做出决定的关键。
权重是层叠的不同阶段之一,在上一个关于层叠的模块中已经介绍过。
权重评分
来源中的每个选择器规则都会获得一个分数。您可以将权重视为总分,每种选择器类型都会为该分数赢得积分。权重最高的规则中的声明获胜。
在实际项目中,使用权重时的平衡之术是确保您期望应用的 CSS 规则确实应用,同时通常保持较低的分数以防止复杂性。权重应该只达到我们需要的程度,而不是追求尽可能最高的权重。将来,可能需要应用一些真正更重要的 CSS。如果您追求最高的权重,您将使这项工作变得困难。
权重不是十进制数字,而是一个由三个组件组成的三元组:A
、B
和 C
。
A
:类似 ID 的权重B
:类似类的权重C
:类似元素的权重
它通常使用 (A,B,C)
表示法表示。例如:(1,0,2)
。另一种 A-B-C
表示法也很常用。
比较权重
权重的比较是通过按顺序比较三个组件来完成的: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)
。选择器的每个部分都会增加权重,具体取决于选择器的类型,会增加 A
、B
或 C
的值。
通用选择器
通用选择器 (*
) 不增加权重,使其值保持在初始权重 (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
(0,0,2)
。article.card.dark
(0,2,1)
。article:hover a[href]
(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;
}
这是因为两个选择器都具有相同的权重。在这种情况下,层叠会回退到出现顺序步骤。