特异性计算
当来源和层相同,特异性帮助浏览器比较匹配规则。可以把它粗略看成 ID、类/属性/伪类、类型/伪元素三列的比较,而不是把数字简单相加。先比较最高列,只有相同才看下一列。
css
#app .card p { color: navy; }
.card p { color: green; }
p { color: gray; }第一条包含 ID,因此在同一层和来源下胜出。!important 不是特异性更高,而是改变声明所处的优先级阶段。:where() 的参数不会增加特异性,:is() 与 :not() 通常取参数中的最高特异性。使用这些机制能降低覆盖复杂度,继续堆选择器会让组件难以维护。
实验与练习
给同一段落写出四条不同特异性的声明,在开发者工具中验证结果。把一个高特异性组件规则改成低特异性层规则,观察是否能减少 !important。解释每次胜出的阶段,而不是只记录最终颜色。
可运行微实验:从匹配到胜出
在一个页面中保留三个同名元素,给它们同时设置类型、类、属性和伪类规则。先在 Elements 的 Matched CSS Rules 记录“命中但未胜出”的声明,再只改变一个条件:元素增加类、属性值改变、祖先增加类或规则移入另一层。每次只记录匹配集合、特异性/层级和最终 computed value,避免把“选择器没命中”和“命中了但被覆盖”混为一谈。
html
<p class="notice" data-state="error">消息</p>
<style>p { color: gray } .notice { color: navy } [data-state="error"] { color: crimson }</style>常见错误
- 把特异性三列相加成一个普通整数。
- 认为更长的选择器一定胜出。
- 使用 ID 和嵌套选择器解决一次性覆盖。
- 以为
!important是特异性数值最大。
继续阅读
不是所有属性都需要直接匹配。下一篇解释未被声明覆盖时,值如何从祖先传播:继承与控制关键字。
练习
- 用最小输入复现“特异性计算”的成功路径,并记录可观察结果。
- 改变一个时序、数据或宿主条件,解释结果为何变化。
- 删除清理、校验或降级分支,写出能证明缺陷的断言。