深入理解 CSS 选择器、层叠与优先级机制
本文系统梳理 CSS 的核心运行逻辑,涵盖选择器类型、层叠规则、优先级计算(个十百千法则)、伪类/伪元素应用及常见布局陷阱,助你写出更精准、可维护的样式代码。
一、CSS 是什么?
CSS(Cascading Style Sheets,层叠样式表)由 声明(Declaration) 组成:
- 一个声明:
color: red; - 声明块:多个声明包裹在
{}中; - 规则集(Rule Set) = 选择器 + 声明块;
- 多个规则集构成样式表。
p {
color: blue; /* 声明 */
font-size: 16px; /* 声明 */
} /* ← 声明块 + 选择器 = 规则集 */
二、“层叠”到底是什么意思?
层叠(Cascading) 是 CSS 的核心机制,决定当多个规则作用于同一元素时,哪条规则最终生效。其依据包括:
- 来源顺序(后写的覆盖先写的);
- 选择器优先级;
!important(慎用!);- 继承与默认值。
💡 层叠 ≠ 继承。层叠解决“谁赢”,继承解决“从哪来”。
三、CSS 选择器优先级:个十百千法则
优先级按 四位数 计算:[内联, ID, 类/伪类/属性, 元素/伪元素]
| 选择器类型 | 权重示例 |
|---|---|
内联样式 (style="") | 1,0,0,0 |
ID 选择器 (#main) | 0,1,0,0 |
类/属性/伪类 (.btn, [type], :hover) | 0,0,1,0 |
元素/伪元素 (p, ::before) | 0,0,0,1 |
通配符 *、组合符(>, +) | 0,0,0,0 |
示例验证:
<div id="main" class="container">
<p>这是一个段落</p>
</div>
p { color: blue; } /* 0,0,0,1 */
.container p { color: red; } /* 0,0,1,1 */
#main p { color: green; } /* 0,1,0,1 → 最终生效 */
✅ 结论:ID 选择器权重高于类,绿色胜出。
⚠️ 避免滥用
!important,它会破坏层叠逻辑,增加调试难度。
四、常用选择器详解
1. 后代 vs 子代
.container p /* 后代选择器:所有嵌套的 p */
.container > p /* 子代选择器:仅直接子元素 p */
2. 相邻与通用兄弟
h1 + p /* 紧跟 h1 的下一个 p */
h1 ~ p /* h1 后所有同级的 p */
3. 属性选择器
[data-category="科幻"] { background: #007bff; }
[title^="入门"] h2::before { content: "🌟"; }
4. 伪类 vs 伪元素
| 类型 | 用途 | 示例 |
|---|---|---|
| 伪类 | 描述元素状态 | :hover, :focus, :nth-child() |
| 伪元素 | 创建虚拟内容/部分 | ::before, ::after, ::selection |
✅ 伪元素必须用双冒号(
::),伪类用单冒号(:)——这是规范区分。
五、nth-child 与 nth-of-type 的区别
<div class="container">
<p>1</p>
<div>div</div>
<p>2</p>
<p>3</p>
</div>
p:nth-child(3)→ 无效!第 3 个子元素是<p>吗?不是,是<div>。p:nth-of-type(3)→ 选中第 3 个<p>元素(即内容为“3”的段落)。
📌
nth-of-type更安全,推荐用于混合标签结构。
六、样式来源优先级(从低到高)
- 浏览器默认样式(User Agent)
- 用户自定义样式(极少用)
- 外联样式
<link> - 内嵌样式
<style> - 行内样式
style="" !important(覆盖一切,但破坏可维护性)
🚫 行内样式难以复用且优先级过高,应尽量避免。
七、其他实用知识点
-
margin 重叠:垂直方向相邻块元素的 margin 会合并,取最大值;
-
小数像素处理:浏览器会四舍五入或亚像素渲染(如
10.5px); -
inline 元素限制:
- 不支持
width/height; transform在部分浏览器中失效;- 解决方案:转为
inline-block或position: absolute。
- 不支持
总结
- CSS 的核心是 层叠 + 选择器 + 优先级;
- 掌握 个十百千法则,避免盲目使用
!important; - 优先使用语义化选择器(如属性、伪类)提升可读性;
- 伪元素用于装饰,伪类用于交互状态;
- 理解
nth-of-type与nth-child差异,避免选错元素。
✨ 最佳实践:用类名控制样式,少用 ID;结构清晰,优先级自然可控。