CSS 选择器
选择器是 CSS 的"瞄准镜"——决定每条规则作用到哪些元素。掌握常用选择器,日常开发 90% 的场景就够用了。这一篇我们把所有常用选择器系统过一遍,最后讲清最让人头疼的"优先级"问题。
1. 基础选择器
这四种是最基本的,几乎每段 CSS 都会用到。
/* 标签选择器:选中所有某类元素 */
h1 { color: #333; }
p { line-height: 1.6; }
a { color: #4f8cff; }
/* 类选择器:选中带 class="btn" 的元素(最常用) */
.btn { padding: 8px 16px; }
.card { background: #fff; }
/* ID 选择器:选中 id="hero" 的元素(页面唯一) */
#hero { background: #f0f0f0; }
/* 通配符:选中所有元素(性能差,少用) */
* { box-sizing: border-box; }- 标签选择器:直接写标签名,选中页面所有同类元素。适合做全局基础样式(比如所有
p的行高)。 - 类选择器(
.类名):选中带某个 class 的元素。这是实际开发中最常用的选择器,因为类可以重复、可以组合,灵活。 - ID 选择器(
#id):选中带某个 id 的元素。一个页面里 id 必须唯一,所以它只能命中一个元素,优先级又高,实际写样式很少用,主要留给 JS 锚点定位。 - 通配符(
*):选中所有元素。性能稍差,只在全局 reset 时用(比如设 box-sizing)。
2. 一个元素可以有多个类
HTML 里 class 属性可以写多个类名,空格分隔。CSS 可以单独命中其中任何一个,也可以用"连写"要求同时具有多个类才命中——这是组合样式的关键技巧。
<!-- 一个元素可以同时有多个类,空格分隔 -->
<div class="card large highlight">内容</div>
/* 任何一个类都能选中它 */
.card { ... }
.large { ... }
.highlight { ... }
/* 连写:同时具有多个类才命中(中间无空格) */
.card.large { font-size: 1.2rem; }
.card.highlight { border-color: #ff0; }注意 .card.large(中间无空格)和 .card .large(中间有空格)完全是两回事:前者要求"同一个元素同时具有两个类",后者是后代选择器。这是新手最容易混淆的点。
3. 组合选择器(关系)
把多个选择器用空格、>、+、~ 连起来,可以基于元素之间的关系选中目标。四种组合符:
/* 后代选择器(空格):nav 里的所有 a,不管嵌套多深 */
nav a { color: #4f8cff; }
/* 子代选择器(>):只选 nav 的"直接"子元素 a,不选孙级 */
nav > a { color: red; }
/* 相邻兄弟(+):紧贴在 h1 后面的第一个 p */
h1 + p { font-size: 1.1rem; }
/* 通用兄弟(~):h1 之后所有的同级 p */
h1 ~ p { color: #666; }- 空格(后代):选中所有匹配的后代,不管嵌套多深。最常用。
>(子代):只选中直接子元素,不选孙级。比后代选择器更精确,性能也更好。+(相邻兄弟):选中紧挨在某元素后面的同级元素,只命中一个。~(通用兄弟):选中某元素后面所有的同级元素,可以多个。
4. 属性选择器
根据 HTML 属性来选中元素,在做表单、链接样式时特别有用。^ 表示开头、$ 表示结尾、* 表示包含。
/* 选中带 href 属性的 a */
a[href] { color: #4f8cff; }
/* 精确匹配:href 等于某值 */
a[href="https://example.com"] { ... }
/* 以某值开头:href 以 https 开头 */
a[href^="https"] { ... }
/* 以某值结尾:src 以 .png 结尾 */
img[src$=".png"] { ... }
/* 包含某子串:class 列表里包含 active */
div[class*="active"] { ... }5. 伪类(状态与结构)
伪类以单冒号开头,选中处于某种状态的元素——比如鼠标悬停、被选中、是第几个孩子。这是 CSS 里最丰富的能力之一。
/* :hover 光标悬停时 */
.btn:hover { background: #3a78e0; }
/* :focus 输入框获得焦点时 */
input:focus { border-color: #4f8cff; }
/* :first-child 第一个子元素 */
li:first-child { font-weight: bold; }
/* :last-child 最后一个子元素 */
li:last-child { border-bottom: none; }
/* :nth-child(n) 第 n 个子元素 */
li:nth-child(2) { color: red; } /* 第 2 个 */
li:nth-child(odd) { background: #f5f5f5; } /* 奇数行 */
li:nth-child(even) { background: #fff; } /* 偶数行 */
/* :not() 排除某些元素 */
li:not(:first-child) { margin-top: 8px; }最常用的几个::hover(悬停)、:focus(聚焦)、:first-child / :last-child(首/尾孩子)、:nth-child()(第 n 个)、:not()(排除)。
:nth-child() 的参数很灵活:2 是第 2 个,odd 是奇数行,even 是偶数行,3n 是每 3 个一次。表格斑马纹、列表间隔分隔线都靠它。
6. 伪元素
伪元素以双冒号开头,用来选中元素的某个部分——最常见的是在内容前后插入东西,或选中第一行文字。注意伪元素必须配 content 属性,即使内容为空也要写 content: ""。
/* ::before 在元素内容前插入内容(必须配 content) */
.btn::before {
content: "★";
margin-right: 6px;
}
/* ::after 在元素内容后插入 */
.required::after {
content: "*";
color: red;
}
/* ::first-line 选中第一行文字 */
p::first-line { font-weight: bold; }
/* ::selection 选中用户选中的文字 */
::selection { background: #4f8cff; color: #fff; }::before 和 ::after 非常有用:加图标、加必填星号、做装饰、清除浮动都靠它。但记住——伪元素插入的内容不能被选中复制,所以重要信息千万别用伪元素放,只用来做装饰。
7. 优先级(Specificity)
当多条规则作用到同一个元素时,浏览器怎么决定听谁的?这就靠优先级。规则有点像"计位":ID 最强,类其次,标签最弱。下面按优先级从低到高排列:
/* 优先级从低到高 */
/* 1. 标签选择器(权重 0,0,0,1) */
div { color: black; }
/* 2. 类/属性/伪类(权重 0,0,1,0) */
.box { color: blue; }
/* 3. ID(权重 0,1,0,0) */
#main { color: red; }
/* 4. 行内样式(权重 1,0,0,0,最高) */
<p style="color: green;">行内</p>
/* !important 强制最高优先级(慎用) */
.box { color: orange !important; }具体计算方式是把选择器拆成 (a, b, c) 三位数:
a= ID 选择器的个数b= 类、属性、伪类的个数c= 标签、伪元素的个数
从左到右逐位比较,大的赢。比如 #nav .item(1,1,0) > .menu .item:hover(0,3,0) > div ul li(0,0,3)。优先级相同时,后写的覆盖先写的。
两个忠告:
- 优先用类,少用 ID,几乎不用行内样式。这样优先级清晰、好覆盖、好维护。
- 慎用
!important。它打破优先级规则,看似省事实则挖坑——后面想覆盖只能再叠!important,最后变成军备竞赛。除非覆盖第三方库样式,否则不要用。
小结
选择器是 CSS 的核心武器。掌握基础(标签/类/ID)、组合(空格/>/+/~)、伪类、伪元素,加上理解优先级,你就能精准命中任何想改的元素。下一篇讲盒模型——理解了盒子,布局才算开了门。
← 上一篇 CSS 语法与引入方式
下一篇 CSS 盒模型 →