CSS选择器入门
# 01.CSS选择器入门
从零掌握 CSS 的核心机制:语法与引入方式、层叠与继承规则、选择器全族谱(基础/组合/伪类/伪元素)、特异性计算公式、
!important的正确使用策略。
# 1. CSS 语法与引入方式
# 1.1 基本语法
一条 CSS 规则由选择器和声明块组成:
选择器 { 属性: 值; 属性: 值; }
/* 选择器:h1 声明块:花括号内的所有内容 */
h1 {
color: red; /* 属性: color,值: red */
font-size: 24px; /* 属性: font-size,值: 24px */
}
每行声明以分号结尾(最后一条可省略,但推荐均保留)。CSS 忽略多余空格和换行,以下三种写法等价:
h1 { color: red; font-size: 24px; }
h1 {
color: red;
font-size: 24px;
}
h1
{ color: red; font-size: 24px; }
# 1.2 三种引入方式
| 方式 | 语法 | 优先级 | 适用场景 |
|---|---|---|---|
| 外部样式表 | <link rel="stylesheet" href="style.css"> | 中 | 生产环境首选 |
| 内部样式表 | <style>h1 { color: red; }</style> | 中 | 单页原型/演示 |
| 行内样式 | <h1 style="color: red;"> | 最高 | 动态样式/邮件HTML |
<!DOCTYPE html>
<html>
<head>
<!-- 方式一:外部样式表(推荐) -->
<link rel="stylesheet" href="style.css">
<!-- 方式二:内部样式表 -->
<style>
p { font-size: 16px; }
</style>
</head>
<body>
<!-- 方式三:行内样式 -->
<h1 style="color: red;">标题</h1>
</body>
</html>
外部样式表 是生产环境的标准做法——样式与结构分离,浏览器可缓存 CSS 文件,多页面共享一份样式。
# 1.3 CSS 注释
/* 单行注释 */
h1 { color: red; }
/*
* 多行注释
* 适合描述复杂逻辑
*/
不同于 HTML 的 <!-- --> 和 JS 的 //,CSS 只有 /* */ 一种注释格式。
# 2. 层叠与继承
# 2.1 层叠(Cascade)——"谁说了算"
当多条规则同时匹配同一元素时,浏览器按层叠顺序决定最终生效的样式:
层叠优先级(从低到高):
① 用户代理样式(浏览器默认样式)
② 用户样式(用户在浏览器设置中的自定义)
③ 作者样式(开发者写的 CSS)
├── 外部样式表
├── 内部样式表(与外部同级,按引入顺序)
└── 行内样式(高于外部/内部)
④ 作者样式中的 !important
⑤ 用户样式中的 !important
⑥ 用户代理样式中的 !important
/* 外部 style.css */
p { color: blue; } /* ① 优先级最低 */
/* 内部 <style> */
p { color: green; } /* ② 同优先级,后写覆盖前写 */
/* 行内 */
<p style="color: red;"> /* ③ 高于外部/内部 */
/* 最终显示:红色 */
# 2.2 继承(Inheritance)——"子承父业"
某些 CSS 属性会自动从父元素传递给子元素:
可继承属性(常见):
color、font-family、font-size、font-weight、
line-height、text-align、visibility、cursor
不可继承属性(常见):
width、height、margin、padding、border、
background、position、display、overflow
<style>
body { color: red; font-size: 18px; }
</style>
<body>
<p>这段文字是红色 18px</p> <!-- 继承自 body -->
<div>
<span>也是红色 18px</span> <!-- 继续向下传递 -->
</div>
</body>
四个控制继承的关键字:
.child {
color: inherit; /* 强制继承父元素值(默认行为) */
color: initial; /* 重置为属性的初始值 */
color: unset; /* 可继承 → inherit,不可继承 → initial */
color: revert; /* 回退到浏览器默认样式 */
}
| 关键字 | 行为 | 典型用途 |
|---|---|---|
inherit | 强制继承父值 | 让 <a> 继承父容器颜色 |
initial | 重置为 CSS 规范初始值 | 消除第三方库的样式污染 |
unset | 智能重置 | 通用重置方案 |
revert | 回退浏览器默认 | 组件内部样式隔离 |
# 3. 基础选择器
# 3.1 类型选择器(标签选择器)
选中所有匹配的 HTML 标签:
p { color: blue; } /* 所有 <p> 标签 */
h1 { font-size: 32px; } /* 所有 <h1> 标签 */
# 3.2 类选择器
. 开头,可复用,一个元素可有多个类:
<style>
.highlight { background: yellow; }
.large-text { font-size: 24px; }
</style>
<p class="highlight">高亮段落</p> <!-- 单个类 -->
<p class="highlight large-text">高亮且大字</p> <!-- 多个类 -->
# 3.3 ID 选择器
# 开头,每个页面唯一:
<style>
#header { background: #333; color: white; }
</style>
<div id="header">页面头部</div>
⚠️ ID 选择器的特异性极高(见第 6 章),在 CSS 中应优先使用类选择器,ID 保留给 JS 和锚点。
# 3.4 通配选择器
* 匹配所有元素:
* { margin: 0; padding: 0; } /* 全局重置 */
.container * { color: red; } /* 仅 .container 内部的所有元素 */
# 3.5 属性选择器
根据元素的属性和属性值匹配:
| 语法 | 含义 | 示例 |
|---|---|---|
[attr] | 有该属性 | [disabled] 匹配所有禁用元素 |
[attr=val] | 属性值等于 val | [type="text"] 匹配文本输入框 |
[attr~=val] | 属性值包含 val(空格分隔) | [class~="btn"] 匹配 class 含 "btn" |
[attr\|=val] | 属性值等于 val 或 val- 开头 | [lang\|="en"] 匹配 en / en-US |
[attr^=val] | 属性值以 val 开头 | [href^="https"] 匹配 https 链接 |
[attr$=val] | 属性值以 val 结尾 | [src$=".png"] 匹配 PNG 图片 |
[attr*=val] | 属性值包含 val | [title*="hello"] 匹配 title 含 hello |
a[href^="https"] { color: green; } /* 安全链接绿色 */
input[type="email"] { border-color: blue; } /* 邮箱输入框蓝边 */
img[src$=".svg"] { background: #eee; } /* SVG 图片灰底 */
# 4. 组合选择器
# 4.1 后代选择器
A B — A 内部所有层级的 B:
article p { color: gray; } /* article 内的所有 <p>,无论嵌套多深 */
# 4.2 子选择器
A > B — A 的直接子元素 B:
ul > li { border-bottom: 1px solid #ccc; } /* 仅一级 li */
<ul> ← 一级
<li>项目 A</li> ← ul > li 匹配 ✅
<li>项目 B
<ul> ← 二级
<li>子项</li> ← ul > li 不匹配 ❌ (这是内层 ul 的直接子元素)
</ul>
</li>
</ul>
# 4.3 相邻兄弟选择器
A + B — 紧跟在 A 之后的同级 B(仅一个):
h2 + p { margin-top: 0; } /* 紧接 h2 后的第一个 p */
# 4.4 通用兄弟选择器
A ~ B — A 之后的所有同级 B:
h2 ~ p { color: #666; } /* h2 之后的所有同级 p */
# 4.5 选择器列表(并集)
逗号分隔,同时匹配多个选择器:
h1, h2, h3 { font-family: sans-serif; } /* 三个标题统一字体 */
.error, .warning { border-left: 4px solid red; }
# 5. 伪类与伪元素
# 5.1 伪类(Pseudo-classes)
表示元素的特定状态,以 : 开头:
链接与交互状态:
a:link { color: blue; } /* 未访问的链接 */
a:visited { color: purple; } /* 已访问的链接 */
a:hover { color: red; } /* 鼠标悬停 */
a:active { color: orange; } /* 点击瞬间 */
a:focus { outline: 2px solid; } /* 键盘聚焦 */
/* LVHA 顺序记忆口诀:LoVe/HAte */
表单状态:
input:disabled { background: #eee; } /* 禁用状态 */
input:checked { accent-color: green; } /* 勾选状态 */
input:focus { border-color: blue; } /* 聚焦 */
input:invalid { border-color: red; } /* 验证失败 */
input:required { border-left: 3px solid; } /* 必填字段 */
:nth-child 家族(最强大的结构伪类):
li:first-child { font-weight: bold; } /* 第一个子元素 */
li:last-child { border-bottom: none; } /* 最后一个 */
li:nth-child(odd) { background: #f0f0f0; } /* 奇数行(斑马条纹) */
li:nth-child(even) { background: white; } /* 偶数行 */
li:nth-child(3) { color: red; } /* 第3个 */
li:nth-child(2n+1) { } /* 等价于 odd */
li:nth-child(-n+3) { } /* 前3个 */
/* An+B 公式解读:
n=0: A×0+B = B (第 B 个)
n=1: A×1+B = A+B (第 A+B 个)
n=2: A×2+B = 2A+B (第 2A+B 个)
*/
:nth-of-type 与 :nth-child 的区别:
/* :nth-child 在所有兄弟中计数,不区分类型 */
div p:nth-child(2) { } /* div 中第2个子元素,且必须是 p */
/* :nth-of-type 仅在同类型兄弟中计数 */
div p:nth-of-type(2) { } /* div 中第2个 p 元素 */
:not() 否定伪类:
button:not(.primary) { background: gray; } /* 非主要按钮灰色 */
input:not(:focus) { opacity: 0.7; } /* 非聚焦时半透明 */
/* 链式否定 */
div:not(.active):not(.disabled) { }
# 5.2 伪元素(Pseudo-elements)
表示元素的虚拟子元素,以 :: 开头(兼容旧写法 :):
/* ::before / ::after — 在元素内部插入虚拟内容 */
.quote::before { content: "「"; color: gray; }
.quote::after { content: "」"; color: gray; }
/* 渲染效果:<blockquote class="quote">引用的文字</blockquote>
显示为: 「引用的文字」 */
/* ::first-line — 首行 */
p::first-line { font-weight: bold; }
/* ::first-letter — 首字 */
p::first-letter { font-size: 3em; float: left; } /* 首字下沉 */
/* ::selection — 用户选中文本 */
::selection { background: #ff0; color: #333; }
/* ::placeholder — 输入框占位文本 */
input::placeholder { color: #999; font-style: italic; }
/* ::marker — 列表项标记(li 前的圆点/数字) */
li::marker { color: red; font-weight: bold; }
伪类 vs 伪元素速记:
| 类型 | 符号 | 本质 | 示例 |
|---|---|---|---|
| 伪类 | : | 元素的状态 | :hover, :nth-child(2), :focus |
| 伪元素 | :: | 虚拟的子元素 | ::before, ::after, ::first-line |
# 6. 特异性(Specificity)计算
当多条规则冲突时,浏览器用特异性值决定优胜者。
# 6.1 四元组计算法
把每条选择器的特异性拆解为 (a, b, c, d) 四元组:
a = 行内样式 (style=""),有则 a=1
b = ID 选择器数量
c = 类/属性/伪类 选择器数量
d = 类型/伪元素 选择器数量
比较规则:从左到右逐位比较,高位大的胜出
| 选择器 | a | b | c | d | 特异性 |
|---|---|---|---|---|---|
style="" | 1 | 0 | 0 | 0 | (1,0,0,0) |
#header | 0 | 1 | 0 | 0 | (0,1,0,0) |
.btn.primary | 0 | 0 | 2 | 0 | (0,0,2,0) |
div p | 0 | 0 | 0 | 2 | (0,0,0,2) |
#nav .item a:hover | 0 | 1 | 2 | 1 | (0,1,2,1) |
* 通配符 | 0 | 0 | 0 | 0 | (0,0,0,0) |
# 6.2 实战演练
<style>
/* 特异性 (0,0,0,1) */
p { color: blue; }
/* 特异性 (0,0,1,0) */
.intro { color: green; }
/* 特异性 (0,0,1,1) */
p.intro { color: red; }
</style>
<!-- class="intro" 同时被三条规则匹配 -->
<p class="intro">红色</p> <!-- p.intro 特异性最高,胜出 -->
常见误区:
/* 误区:认为"后写的覆盖先写的" */
ul li { color: red; } /* 特异性 (0,0,0,2) */
#nav li { color: blue; } /* 特异性 (0,1,0,1) */
/* → 蓝色胜出,即使它写在前 */
# 6.3 特异性计算口诀
行内 ID 类 标签 → (a, b, c, d)
从左到右比,高位定胜负
永远不要凭书写顺序判断优先级(同特异性时除外)
# 7. !important 的正确策略
!important 打破正常层叠规则,强制覆盖:
p { color: red !important; } /* 特异性跃迁到最高层 */
# 7.1 优先级提升效果
正常层叠(从低到高):
标签 < 类 < ID < 行内样式
加入 !important 后:
标签 < 类 < ID < 行内 < !important
(!important 之间仍按特异性比较)
p { color: red !important; } /* !important */
#content p { color: blue; } /* ID + 标签,但无 !important */
/* → 红色胜出,因为 !important 覆盖正常优先级 */
# 7.2 使用原则(必读)
| ✅ 可以用的场景 | ❌ 不能用的场景 |
|---|---|
| 覆盖第三方库的侵入式样式 | 解决自己代码的特异性不足 |
工具类(.hidden { display: none !important; }) | 偷懒不重构选择器 |
| 覆盖 JS 动态注入的行内样式 | 组件内部日常样式 |
/* ✅ 正确:覆盖第三方轮播图库的默认样式 */
.swiper-pagination-bullet {
background: var(--brand-color) !important;
}
/* ❌ 错误:自己写的样式不该用 !important */
.card { width: 200px !important; } /* 应该提高选择器特异性 */
# 7.3 !important 调试技巧
当发现 !important 互相冲突时,排查链:
1. 打开 DevTools → 选中目标元素
2. 查看 Styles 面板,被划掉的声明是被覆盖的
3. 找到生效声明中的 !important
4. 追溯到源文件 → 考虑重构选择器链
# 实战建议
1. 选择器尽量短(≤ 3 层嵌套),避免 (0,0,4,0) 以上的高特异性
2. 优先使用类选择器,少用 ID 和标签选择器
3. BEM 命名法天然避免特异性冲突
4. :not() 可提高特异性但不可滥用
5. 遇到特异性不足时,优化 HTML 结构优于加 !important
下一篇:02.CSS盒模型详解 — 从 content-box 到 border-box,揭开 CSS 布局的底层基石。