1. 引言
在 CSS 中,选择器是连接 HTML 结构与样式的桥梁。当页面元素越来越多时,如果为每个元素单独写一条规则,样式表会变得冗长且难以维护。分组选择器 和链接伪类选择器正是解决这类问题的两把利器:前者帮我们把相同样式一次性套用到多个选择器上,后者则让超链接拥有「未访问、已访问、悬停、按下」等不同状态下的差异化表现。
本文将从语法、原理到实战,系统讲解这两类选择器的用法与常见坑点。
2. 分组选择器(Grouping Selector)
2.1 基本语法
分组选择器使用英文逗号 , 将多个选择器并列,表示「这些选择器共享同一组声明」:
css
h1, h2, h3, p {
margin: 0;
line-height: 1.6;
color: #333;
}
上面这条规则等价于分别写四条 h1 { ... }、h2 { ... } 等规则,但代码量大幅减少,后期修改也只需改一处。
2.2 逗号的含义:逻辑「或」
分组选择器中的逗号表示逻辑或关系:只要元素匹配其中任意一个选择器,就会应用后面的声明块。这一点与后代选择器中的空格(逻辑「与」)截然不同:
css
/* 逻辑或:h1 或 h2 或 h3 */
h1, h2, h3 { color: red; }
/* 逻辑与:位于 .card 内部的 h1 */
.card h1 { color: blue; }
2.3 分组选择器的常见组合
分组选择器可以混合任意类型的选择器,包括类、ID、属性、伪类等:
css
/* 类选择器 + 属性选择器 + 伪类 */
.btn,
input[type="submit"],
a:hover {
cursor: pointer;
text-decoration: none;
}
2.4 一个容易踩的坑:逗号写错位置
初学者常把逗号写成「最后一个选择器后面也加逗号」,或者漏写逗号导致整条规则失效:
css
/* 错误:末尾多余逗号,整条规则会被浏览器丢弃 */
h1, h2, h3, {
color: red;
}
/* 正确 */
h1, h2, h3 {
color: red;
}
提示:CSS 解析器遇到非法选择器时,通常会丢弃整条规则,而不是只忽略出错的部分。因此分组选择器里只要有一个选择器写错,整组样式都不会生效。
3. 链接伪类选择器(Link Pseudo-classes)
3.1 什么是伪类
伪类(pseudo-class)以冒号 : 开头,用于描述元素的特定状态 ,而不是元素本身的结构。链接伪类专门用于 <a> 标签,描述链接在不同交互阶段的状态。
3.2 四个链接伪类
| 伪类 | 含义 | 触发时机 |
|---|---|---|
:link |
未访问过的链接 | 链接从未被点击过 |
:visited |
已访问过的链接 | 浏览器历史中存在该地址 |
:hover |
鼠标悬停 | 指针停留在元素上 |
:active |
激活状态 | 鼠标按下且尚未释放 |
示例:
css
/* 未访问 */
a:link {
color: #1a73e8;
text-decoration: none;
}
/* 已访问 */
a:visited {
color: #7b1fa2;
}
/* 悬停 */
a:hover {
color: #d93025;
text-decoration: underline;
}
/* 按下 */
a:active {
color: #f9ab00;
}
3.3 LVHA 顺序原则
链接伪类的书写顺序非常重要,业界总结为 LVHA(LoVe HAte):
text
:link → :visited → :hover → :active
原因在于 CSS 的层叠与优先级 :这四个伪类的优先级相同(都是 0,1,0),后写的规则会覆盖先写的。如果 :visited 写在 :hover 之后,那么已访问链接在悬停时仍会显示 :visited 的颜色,悬停效果就「失效」了。
css
/* 错误顺序:hover 被 visited 覆盖 */
a:hover { color: red; }
a:visited { color: purple; }
/* 正确顺序 */
a:visited { color: purple; }
a:hover { color: red; }
3.4 :visited 的安全限制
出于隐私保护,浏览器对 :visited 做了严格限制:只能修改颜色类属性 (如 color、background-color、border-color 等),且 getComputedStyle 会返回未访问状态的值。因此不要指望用 :visited 改变字体大小、背景图片或布局。
css
/* 允许 */
a:visited { color: #7b1fa2; }
/* 无效:浏览器会忽略 */
a:visited { font-size: 20px; }
3.5 现代写法::any-link 与 :focus-visible
除了传统四伪类,现代 CSS 还提供了更简洁的替代方案:
css
/* :any-link 同时匹配 :link 和 :visited */
a:any-link {
color: #1a73e8;
}
/* 键盘聚焦时显示轮廓,鼠标点击时不显示 */
a:focus-visible {
outline: 2px solid #1a73e8;
outline-offset: 2px;
}
4. 两者结合:分组 + 伪类的实战
分组选择器与链接伪类经常一起使用,例如统一站点内所有链接与按钮的交互反馈:
css
/* 所有链接和按钮在悬停时统一变暗 */
a:hover,
button:hover,
.btn:hover {
filter: brightness(0.9);
}
/* 导航栏中的链接:未访问与已访问使用同一基础色 */
.nav a:link,
.nav a:visited {
color: #fff;
padding: 8px 16px;
}
/* 导航栏链接悬停与聚焦时高亮 */
.nav a:hover,
.nav a:focus-visible {
background-color: rgba(255, 255, 255, 0.15);
border-radius: 4px;
}
5. 常见问题与最佳实践
- 不要用
:visited做布局:受隐私限制,只有颜色类属性生效。 - 牢记 LVHA 顺序:顺序错误是链接样式「不生效」的头号原因。
- 分组选择器注意可读性:选择器过多时建议换行书写,每个选择器独占一行,便于 diff 与维护。
- 避免过度分组:把语义完全无关的选择器强行分组,会让样式难以追踪,建议按模块拆分。
- 优先使用
:any-link:当:link与:visited样式一致时,用:any-link可减少重复代码。
6. 总结
分组选择器通过逗号实现「一处声明、多处复用」,是压缩样式表、统一视觉规范的基础手段;链接伪类则通过 :link、:visited、:hover、:active 描述链接的四种状态,配合 LVHA 顺序才能正确生效。掌握这两类选择器,既能写出更简洁的 CSS,也能避免大量「样式为什么不生效」的排查时间。