第二章 · 2.2 节
组合选择器与优先级
把基础选择器按不同的连接符组合起来,就能精确描述元素之间的结构关系。理解这四种组合方式,再加上一套优先级计算规则,就能预判任何一条 CSS 规则最终会不会生效。
后代选择器(空格)
两个选择器之间以空格分隔,匹配前者内部任意深度的后代元素,不要求直接嵌套。
.article p { color: #5c5872; }
无论 p 是 .article 的直接子元素,还是被包裹在多层 div 中,都会命中。
子代选择器(>)
只匹配直接子元素,不会穿透更深的层级,常用于避免样式意外污染嵌套组件。
.nav > li { display: inline-block; }
实践建议在编写组件库样式时,优先使用子代选择器而非后代选择器,能有效避免样式"渗透"进组件内部嵌套的同名标签。
相邻兄弟选择器(+)
匹配紧跟在前一个元素之后、且拥有相同父元素的下一个兄弟节点。
h2 + p { margin-top: 0; }
效果预览:紧邻标题的段落取消上边距
小标题
紧跟其后的段落,margin-top 被清零。
通用兄弟选择器(~)
匹配同一父元素下、在前一个元素之后出现的所有符合条件的兄弟节点,不要求紧邻。
.tab-radio:checked ~ .tab-panel { display: block; }
这也是"纯 CSS 标签页 / 手风琴"技巧的核心原理:借助 :checked 状态与通用兄弟选择器联动,无需 JavaScript。
优先级计算
当多条规则同时命中同一元素的同一属性时,浏览器按"优先级"高低决定生效的声明。优先级由四个等级构成,从高到低依次为:
| 等级 | 示例 | 权重记法 |
|---|---|---|
| 内联样式 | style="color:red" | 1,0,0,0 |
| ID 选择器 | #nav | 0,1,0,0 |
| 类 / 属性 / 伪类 | .btn / [type] / :hover | 0,0,1,0 |
| 标签 / 伪元素 | div / ::before | 0,0,0,1 |
逐级比较,高位相同再比下一位;!important 会越过以上所有等级,应当谨慎使用。例如 .nav .item.active 的权重是 0,0,2,0,高于 .item(0,0,1,0),但低于 #nav .active(0,1,1,0)。
.item { color: gray; } /* 0,0,1,0 */ .nav .item.active { color: teal; } /* 0,0,2,0 —— 生效 */
层叠与来源顺序
当两条规则优先级完全相同时,"层叠"(Cascade)规则介入:后声明的规则覆盖先声明的规则。这也是为什么 CSS 文件的书写顺序、以及 <link> 标签的引入顺序会影响最终效果。现代 CSS 还引入了 @layer 层叠层,可以显式控制不同来源样式之间的覆盖关系,这里先作了解,留待进阶主题展开。