浏览器对每个元素的每个属性只保留一条获胜声明。裁判的判序是:① 来源与重要性 → ② 层(@layer)→ ③ 权重 → ④ 书写顺序。前三步比不出才看谁写在后面。
| 成分 | 来自 | 数量级 |
|---|---|---|
| id 的个数 | #buy | 1,0,0 |
| class / 属性 / 伪类的个数 | .btn、[type=text]、:hover、:not() 内部的参数 | 0,1,0 |
| 类型(元素名)与伪元素的个数 | p、::before | 0,0,1 |
下面三条规则都命中同一个按钮,最终是红色:
.page .btn { color: #8250df; } /* 0,2,0 */
.btn.primary { color: #0969da; } /* 0,2,0 —— 与上一条同权重,写在后面才胜出 */
#buy.primary { color: #cf222e; } /* 1,1,0 ← 赢 */
立即购买
三个常见误解:① 权重不是十进制,11 个 class 也压不过 1 个 id(0,11,0 vs 1,0,0);② * 和组合子(> + ~ 空格)权重为 0;③ :where() 权重为 0,而 :is() 取参数里最高的那个(第十五章)。元素的 style="" 不参与这套计数,它比所有规则都高(除了 !important)。
.imp-a { color: #57606a; }
.imp-b { color: #1a7f37 !important; }
#hardcoded { color: #0969da; } /* 权重 1,0,0 仍然输给带 !important 的 .imp-b */
这一行是绿色:!important 赢了权重
用了它,唯一的反制手段是更具体的选择器 + 另一个 !important,或者用内联 style 加 !important。项目里出现「为了盖住一行 !important 再加一行 !important」就说明已经失控。合理的用法只有三类:第三方样式表的临时补丁、工具类(如 .visually-hidden)、用户样式表(无障碍场景)。
这一层设了 color:#cf222e、等宽字体、line-height:1.9。
子元素没写任何 color,但它是红的、等宽的、行高 1.9 → color/font-*/line-height/text-align/visibility/cursor 都继承。
这里写了 color: initial → 回到该属性的初始值(黑),继承被切断。
| 继承 | 不继承 |
|---|---|
color、font-*、line-height、text-*、letter-spacing、visibility、cursor、writing-mode | 盒模型(margin/padding/border/width/height)、background、display、position 与定位、flex/grid 全部、overflow、opacity、transform |
/* 四个关键字,随时手动改变继承行为 */ color: inherit; /* 强制继承父元素的值 */ color: initial; /* 强制回到该属性的初始值 */ color: unset; /* 可继承属性 = inherit,不可继承属性 = initial */ color: revert; /* 回到「上一层来源」的值,通常是浏览器默认样式 */
revert 与 unset 的区别很实用:浏览器给 ul 的默认 padding-inline-start: 40px,写 unset 得到 0,写 revert 也是回到默认——但当你想「恢复到用户代理样式表」或「撤销用户自己的覆盖样式」时,只有 revert 正确。另有 revert-layer 撤销当前 @layer 的层内结果(第十六章)。
!important 压制,面板会直接标出是谁压的。color: initial 试一下,值变了说明原来那个值是继承来的。