掌握两个新的级联判定标准——层与作用域邻近度——从而在不打特异性大战的情况下架构你的样式。
在 Kodokon 中打开本课级联通过一系列有序的判定标准来解决相互冲突的声明:来源与重要性,然后是上下文,然后是 style 属性内的样式,然后是层(@layer),然后是特异性,最后是出现顺序。关键在于:层的评估在特异性之前。因此,位于更高优先级层中的一条 .button 规则,会击败位于更低优先级层中的 #nav div.menu a.button——后者 (1,2,2) 的特异性在层顺序面前毫无价值。这正是 @layer 在架构设计系统时如此强大的原因:优先级只需在结构上声明一次,而不必逐个选择器地去争夺。
@layer reset, base, components, utilities;
@layer components {
.button { background: rebeccapurple; }
}
@layer base {
button { background: gray; }
}有两个你绝对需要了解的规范细节。其一:位于任何层之外的样式会击败层内样式(对于普通声明而言)——它们构成一个被置于最后的隐式层。因此你本地的覆盖始终会击败已分层的库。其二:一旦使用 !important,顺序会完全反转。最先声明的层获胜,而层内的 !important 会击败任何层之外的 !important。你 reset 层里的一条 !important 声明会变得几乎不可战胜。
@layer base, theme;
@layer base {
a { color: black !important; }
}
@layer theme {
a { color: purple !important; }
}@scope 会把一组规则限定在一个作用域根和一个可选的下边界之间:@scope (.card) to (.card__content) 会命中那些是 .card 后代、但位于 .card__content 之外的元素——这就是著名的甜甜圈作用域,非常适合在不泄漏到注入内容的前提下为组件的外框设置样式。在其内部,:scope 指代根本身。而且 @scope 引入了一个全新的级联判定标准:邻近度。在特异性相等时,作用域根离元素最近的那条规则获胜——这是 BEM 和组合器都从来无法表达的能力。
@scope (.card) to (.card__content) {
:scope {
padding: 1rem;
border: 1px solid oklch(0.85 0.02 260);
}
img { border-radius: 8px; }
}