选择器 — 怎么选中你想改的那个元素
选择器 — 怎么选中你想改的那个元素
这一章讲一件事: 规则里的「选中谁」可以怎么写。 共六类思路:按标签、按类、按 ID、按属性、按状态、按元素之间的关系。 读完你能给一段 HTML 配出「只选中那几颗」的选择器,也知道什么时候该停手别写太长。
1. 这一章在全书链条里的位置
上一章立了规则的结构:选择器 + 声明块。这一章把前半段展开—— 它是「选中」(targeting)这一环的完整语法。但选中了不等于生效: 两条规则选中同一个元素时谁赢,是下一章(层叠与特异性)的事; 本章只管「选得中、选得准、别多选」。
2. 顶层全景:一张 HTML,六种选法
主线例子的输入,一段很常见的导航 HTML:
<nav class="menu">
<ul>
<li><a href="/">首页</a></li>
<li class="active"><a href="/blog">博客</a></li>
</ul>
</nav>图说:<nav> 套着 <ul>(无序列表),里面两个 <li>(列表项)各套一个 <a>(链接);
第二个 <li> 带类名 active,第二个链接的地址是 /blog。
对着它,六种选法各选中几颗:
nav → 选标签:2 个 <li> 之外的 <nav> 本体,1 个
.menu → 选类:<nav>,1 个
li → 选标签:两个 <li>,2 个
.active → 选类:第二个 <li>,1 个
a[href="/blog"] → 选属性:第二个 <a>,1 个
li.active a → 组合:第二个 <li> 里的 <a>,1 个下面逐类讲清。
3. 核心原理:六类选择器
按标签、按类、按 ID:三个基本件
标签选择器(type selector)直接写标签名:p、h1、div——选中页面上所有这个标签。
类选择器(class selector)写 .类名:.highlight 选中所有带 class="highlight" 的元素。
类是给元素贴的标签,一个元素可以贴好几个类(class="card highlight"),
一个类可以贴在任意多个元素上——所以类是日常样式的主力。
ID 选择器写 #id名:#main-header 选中 id="main-header" 的那个元素。
ID 在一个 HTML 页面里必须唯一1——这是 HTML 的规矩,不是 CSS 的。
书里给的使用建议很硬:样式尽量别用 ID,因为它的特异性太高,后面很难覆盖(第 03 章展开)。
这三个里有两个细节容易栽:
类名和 ID 区分大小写。 .box 和 .Box 是两个不同的类2——HTML 里的类名是区分大小写的,
CSS 侧必须一字不差地对上。
一个空格之差,意义全变。 div.active(无空格)选中「带 active 类的 <div>」;
div .active(有空格)选中「<div> 里面的、任何带 active 类的元素」3。
前者是同一个元素的两种条件,后者是两层元素的关系——这是初学者最常写错的一处。
按属性选:属性选择器
input[type="text"] /* 只选「类型是文本」的输入框 */
a[target="_blank"] /* 只选「新窗口打开」的链接 */[属性] 或 [属性="值"]:按 HTML 标签上挂的属性来选4。
文本框得到蓝边框、新窗口链接加粗——这是表单一章的基础工具。
按状态选:伪类(pseudo-class)
button:hover /* 鼠标悬停时 */
li:nth-child(odd) /* 排在奇数位的 <li> */
input:focus /* 被 Tab 键或点击选中时 */伪类选中的是「处于某种状态的元素」,写法是 选择器:状态名。
状态可以是用户交互(悬停 hover、聚焦 focus),也可以是文档里的位置
(第一个孩子 first-child、第 n 个孩子 nth-child(n)、取反 not())5。
它解决的是「同一个元素,用户碰没碰它,长得不一样」这一类问题。
按部位选:伪元素(pseudo-element)
p::first-letter /* 每段的首字母 */
.required::after /* 元素内容之后的位置 */伪元素选中的是「元素内部的某个部位」,写法用双冒号 ::——
比如首字母、第一行、内容之前(::before)、内容之后(::after)、占位提示文字(::placeholder)。
书里那个例子:.required::after { content: " *"; color: red; } 会在每个带 required 类的元素后面
缀一颗红星6——表单的「必填」星号就是这么来的。
单双冒号是两套东西,别混:单冒号管状态,双冒号管部位,这是现代 CSS 的规矩7。
按关系选:组合器(combinator)
四种,记住一张表:
| 名字 | 写法 | 选中什么(回到主线例子) |
|---|---|---|
| 后代 descendant | A B | B 只要是 A 里面的都算:.menu a 选中 2 个链接 |
| 子 child | A > B | B 必须是 A 的直接孩子:ul > li 选中 2 个,.menu > a 选中 0 个(a 是孙子) |
| 相邻兄弟 adjacent | A + B | B 紧跟在 A 后面:li + li 只选中第 2 个 li |
| 通用兄弟 general | A ~ B | B 是 A 后面的所有平级兄弟 |
「后代」不限层级,「子」只认一层——这是两者唯一的差别,也是嵌套深的时候选错的高发区。
全选:通配选择器
* 选中页面上每一个元素8。它不是拿来写普通样式的,而是做「统一重置」:
后面章节会反复出现的起手式 * { box-sizing: border-box; margin: 0; } 就是它的标准用途。
4. 常见模式:卡片与表单
书里给了两个把上面的件组装起来的模式。
卡片布局:只动「卡片内部的元素」,不影响页面上别处的同类元素9——
.card { border: 1px solid #ccc; }
.card h2 { margin-bottom: 10px; }
.card p { font-size: 14px; }.card p 是「后代」的用法:只选中卡片里的段落。它对应的真实界面就是你现在读的这种
「带边框的小面板」。
表单状态反馈:用伪类给用户即时的视觉答复10——
input:invalid { border-color: red; } /* 内容不合规则 → 红框 */
input:focus { outline: 2px solid blue; } /* 选中 → 蓝圈 */这两行能成立,靠的是浏览器自动跟踪「这个输入框当前合不合规则、有没有被选中」—— 不用写一行 JavaScript。
5. 作者的判断与证据
- 「始终用能完成工作的最简单的选择器」——本章的立场句,断言式,无论证11。 支撑它的理由分散在本章各处:写长了「处理起来更慢」、ID 太「强」后面难覆盖。
- 「避免用 ID 做样式」——断言,理由(特异性高难覆盖)到第 3 章才兑现12。
- 「Over-selecting:div.container ul li a 通常没必要,.container a 就够」——经验断言, 与「最简单选择器」立场同源13。
6. 边界与局限
- 这一章的伪类清单只是最常用的五个,没提
:focus-visible、:checked、:root等 (后两个在后面的章节里零星出现)。 - 组合器没提「列组合」(
||表格列)这类生僻成员——速查书只做常用面。 - 完全没提
:has()——2023 年起各大浏览器已支持的选择器(选中「包含某元素的元素」), 成书时(2026 年 2 月)它早已可用,本书未收,是其「现代」口径的一处缺口。
判断(我们的,不是书里的): 本章「最简单选择器」的立场比很多同类书讲得早也讲得硬, 值得作为第一原则记住——它的另一面是第 22 章的 BEM 命名法:当「简单」与「不撞名」冲突时, 现代工程的答案是给元素起好类名,而不是把选择器写长。 如果错,会错在: 在第三方内容注入的场景(富文本、用户评论)里,你没有类名可用, 只能写长的后代选择器——「最简单」原则在那类场景要让位于「没得选」。
7. 可带走的
- 六类选法:标签、类、ID、属性、状态(伪类
:)、部位(伪元素::),再加关系(组合器)和全选(*)。 - 类是主力:可复用、可叠加;ID 留给页面唯一元素,样式里尽量别用112。
.box≠.Box,类名区分大小写2;div.active≠div .active,一个空格就是两层关系3。>只认直接孩子,空格不限层级——嵌套深时选错的头号原因。- 单冒号管状态,双冒号管部位,别混7。
- 伪类让元素「随用户操作换脸」,伪元素能凭空加内容(
::after+content),星号必填标记就是它的作品6。 - 写长选择器之前先停一下:能不能加个类名解决?
8. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 六类选择器总览 | Chapter 2: Selectors Reference | text/03-ch01-1-chapter-overview.txt:11(搜「Basic selectors」) |
| 类名/ID 区分大小写 | 同上 | text/03-ch01-1-chapter-overview.txt:23(搜「not the same as .Box」) |
| 分组选择器(逗号) | 同上 | text/03-ch01-1-chapter-overview.txt:25(搜「Grouping Selectors」) |
| 选择器有不同的「分量」 | 同上 | text/03-ch01-1-chapter-overview.txt:27(搜「weights」) |
| 属性选择器 | 同上 | text/03-ch01-1-chapter-overview.txt:74(搜「Attribute Selectors」) |
| 伪类与常用值 | 同上 | text/03-ch01-1-chapter-overview.txt:87(搜「Pseudo-classes」) |
| 伪元素与常用值 | 同上 | text/03-ch01-1-chapter-overview.txt:102(搜「Pseudo-elements」) |
| 四种组合器表 | 同上 | text/03-ch01-1-chapter-overview.txt:117(搜「Combinators」) |
| 空格之差的坑 | 同上 | text/03-ch01-1-chapter-overview.txt:159(搜「Space Matters」) |
| 单双冒号之辨 | 同上 | text/03-ch01-1-chapter-overview.txt:157(搜「Confusing」) |
| 卡片模式 | 同上 | text/03-ch01-1-chapter-overview.txt:138(搜「Card」) |
| 表单状态反馈 | 同上 | text/03-ch01-1-chapter-overview.txt:145(搜「Form Validation」) |
| 最简单选择器立场 | 同上 | text/03-ch01-1-chapter-overview.txt:171(搜「simplest selector」) |
Footnotes
-
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:72,搜「unique within a single HTML page」)。原文:「Use IDs sparingly; they must be unique within a single HTML page.」 ↩ ↩2 -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:23,搜「not the same as .Box」)。原文:「Class and ID selectors are case-sensitive (e.g., .box is not the same as .Box).」 ↩ ↩2 -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:159,搜「Space Matters」)。原文:div.active(无空格)选中带 active 类的<div>;div .active(有空格)选中<div>内部任何带 active 类的元素。 ↩ ↩2 -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:74,搜「Attribute Selectors」)。原文语法:[attribute]或[attribute="value"];例子input[type="text"]、a[target="_blank"]。 ↩ -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:87,搜「Pseudo-classes」)。原文列出的常用值::hover, :focus, :first-child, :nth-child(n), :not()。 ↩ -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:102,搜「Pseudo-elements」;:113搜「required」)。原文例子:.required::after { content: " *"; color: red; },输出解释为「Elements with the "required" class will show a red asterisk after their content.」 ↩ ↩2 -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:157,搜「Confusing」)。原文:「Modern CSS uses single colon : for pseudo-classes (states) and double colon :: for pseudo-elements (parts).」 ↩ ↩2 -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:31,搜「Universal Selector」)。原文:「Targets every single element on the page.」 ↩ -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:138,搜「Card」)。原文:「Using descendant selectors to style elements inside a specific container without affecting the rest of the page.」 ↩ -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:145,搜「Form Validation」)。原文:「Using pseudo-classes to provide visual feedback to users.」 ↩ -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:171,搜「simplest selector」)。原文:「Always aim for the simplest selector that gets the job done.」 ↩ -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:155,搜「ID Overuse」)。原文:「Avoid using IDs for styling. They are too "strong" (high specificity), making them hard to override later. Use classes instead.」 ↩ ↩2 -
出处:「Chapter 2: Selectors Reference」(
text/03-ch01-1-chapter-overview.txt:153,搜「Over-selecting」)。原文:「Writing div.container ul li a is often unnecessary. .container a is usually enough and faster to process.」 ↩