伪类选择器

学习

伪类选择器

2026-02-23/0/ 编辑


伪类选择器

概述

伪类选择器(Pseudo-class Selectors)用于选择处于特定状态的元素,例如:hover、:focus、:active 等。伪类以冒号 : 开头。

语法

选择器:伪类 {
  属性: 值;
}

常用伪类分类

1. 链接伪类

:link - 未访问的链接

a:link {
  color: blue;
}

:visited - 已访问的链接

a:visited {
  color: purple;
}

:hover - 鼠标悬停

a:hover {
  color: red;
  text-decoration: underline;
}

:active - 激活状态(点击时)

a:active {
  color: orange;
}

注意事项: 链接伪类必须按照以下顺序声明(LVHA 原则):

a:link { /* L */ }
a:visited { /* V */ }
a:hover { /* H */ }
a:active { /* A */ }

2. 用户交互伪类

:focus - 获得焦点

input:focus {
  border-color: #3498db;
  outline: none;
  box-shadow: 0 0 5px rgba(52, 152, 219, 0.5);
}

:focus-within - 子元素获得焦点

.form-group:focus-within {
  border-color: #3498db;
}

:focus-visible - 有焦点指示器时

button:focus-visible {
  outline: 2px solid #3498db;
}

3. 表单伪类

:checked - 选中的复选框/单选框

input[type="checkbox"]:checked + label {
  color: #3498db;
  font-weight: bold;
}

:disabled - 禁用的表单元素

input:disabled {
  background-color: #f5f5f5;
  color: #999;
  cursor: not-allowed;
}

:enabled - 启用的表单元素

input:enabled {
  background-color: #fff;
}

:required - 必填字段

input:required {
  border-color: #e74c3c;
}

:optional - 可选字段

input:optional {
  border-color: #95a5a6;
}

:valid - 验证通过

input:valid {
  border-color: #27ae60;
}

:invalid - 验证失败

input:invalid {
  border-color: #e74c3c;
}

input:invalid::after {
  content: "✗";
  color: #e74c3c;
}

:in-range - 在范围内

input[type="number"]:in-range {
  border-color: #27ae60;
}

:out-of-range - 超出范围

input[type="number"]:out-of-range {
  border-color: #e74c3c;
}

:read-only - 只读

input:read-only {
  background-color: #f5f5f5;
  cursor: not-allowed;
}

:read-write - 可读写

input:read-write {
  background-color: #fff;
}

4. 结构伪类

:first-child - 第一个子元素

li:first-child {
  color: red;
}

:last-child - 最后一个子元素

li:last-child {
  color: blue;
}

:nth-child(n) - 第 n 个子元素

/* 第2个子元素 */
li:nth-child(2) {
  background-color: yellow;
}

/* 奇数位置的子元素 */
li:nth-child(odd) {
  background-color: #f9f9f9;
}

/* 偶数位置的子元素 */
li:nth-child(even) {
  background-color: #f0f0f0;
}

/* 每第3个元素 */
li:nth-child(3n) {
  background-color: #eee;
}

/* 3的倍数 + 1 */
li:nth-child(3n+1) {
  color: red;
}

/* 前3个元素 */
li:nth-child(-n+3) {
  color: blue;
}

/* 从第4个开始 */
li:nth-child(n+4) {
  color: green;
}

:nth-last-child(n) - 倒数第 n 个子元素

/* 倒数第2个元素 */
li:nth-last-child(2) {
  background-color: yellow;
}

:first-of-type - 同类型的第一个子元素

p:first-of-type {
  font-weight: bold;
}

:last-of-type - 同类型的最后一个子元素

p:last-of-type {
  color: blue;
}

:nth-of-type(n) - 同类型的第 n 个子元素

/* 第2个p元素 */
p:nth-of-type(2) {
  color: red;
}

/* 奇数位置的p元素 */
p:nth-of-type(odd) {
  background-color: #f9f9f9;
}

:nth-last-of-type(n) - 同类型的倒数第 n 个子元素

/* 倒数第2个p元素 */
p:nth-last-of-type(2) {
  color: red;
}

:only-child - 唯一的子元素

li:only-child {
  background-color: yellow;
}

:only-of-type - 唯一同类型子元素

p:only-of-type {
  font-weight: bold;
}

5. 目标伪类

:target - 当前锚点目标

#section1:target {
  background-color: #fff3cd;
  border-left: 4px solid #ffc107;
}
<a href="#section1">跳转到第一节</a>
<div id="section1">第一节内容</div>

6. 否定伪类

:not(selector) - 不匹配选择器

/* 选择不是禁用的输入框 */
input:not(:disabled) {
  background-color: #fff;
}

/* 选择第一个之外的列表项 */
li:not(:first-child) {
  margin-top: 10px;
}

/* 选择不是第一和最后一个的元素 */
li:not(:first-child):not(:last-child) {
  padding: 0 20px;
}

7. 语言伪类

:lang(language) - 特定语言

p:lang(zh) {
  font-family: "Microsoft YaHei", sans-serif;
}

p:lang(en) {
  font-family: Arial, sans-serif;
}
<p lang="zh">中文内容</p>
<p lang="en">English content</p>

8. UI 状态伪类

:default - 默认选项

input[type="radio"]:default + label {
  font-weight: bold;
}

:indeterminate - 不确定状态

input[type="checkbox"]:indeterminate {
  opacity: 0.5;
}

9. 空状态伪类

:empty - 空元素

.box:empty {
  display: none;
}

.box:empty::after {
  content: "暂无内容";
  color: #999;
}

权重计算

伪类选择器的权重为 10:

a:hover {
  /* 权重 = 1(a) + 10(:hover) = 11 */
  color: red;
}

.box:nth-child(2) {
  /* 权重 = 10(.box) + 10(:nth-child) = 20 */
  background-color: blue;
}

input:focus:invalid {
  /* 权重 = 1(input) + 10(:focus) + 10(:invalid) = 21 */
  border-color: red;
}

常见应用场景

1. 交互效果

/* 按钮悬停效果 */
.button:hover {
  background-color: #3498db;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}

/* 按钮点击效果 */
.button:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

2. 表单验证

/* 验证成功 */
input:valid {
  border-color: #27ae60;
}

input:valid::after {
  content: "✓";
  color: #27ae60;
}

/* 验证失败 */
input:invalid:not(:placeholder-shown) {
  border-color: #e74c3c;
}

input:invalid:not(:placeholder-shown)::after {
  content: "✗";
  color: #e74c3c;
}

/* 必填字段 */
input:required::before {
  content: "*";
  color: #e74c3c;
}

3. 列表样式

/* 斑马纹效果 */
tr:nth-child(even) {
  background-color: #f9f9f9;
}

/* 第一行和最后一行特殊样式 */
tr:first-child {
  background-color: #f0f0f0;
  font-weight: bold;
}

tr:last-child {
  border-bottom: 2px solid #333;
}

4. 卡片布局

/* 卡片悬停效果 */
.card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}

/* 第一个卡片 */
.card:first-child {
  margin-top: 0;
}

/* 最后一个卡片 */
.card:last-child {
  margin-bottom: 0;
}

5. 图片效果

/* 图片悬停放大 */
img:hover {
  transform: scale(1.1);
  transition: transform 0.3s ease;
}

/* 图片聚焦 */
img:focus {
  outline: 3px solid #3498db;
}

6. 自定义复选框

/* 隐藏原生复选框 */
input[type="checkbox"] {
  display: none;
}

/* 自定义样式 */
input[type="checkbox"] + label {
  display: inline-block;
  width: 20px;
  height: 20px;
  border: 2px solid #ccc;
  border-radius: 4px;
  cursor: pointer;
}

/* 选中状态 */
input[type="checkbox"]:checked + label {
  background-color: #3498db;
  border-color: #3498db;
}

input[type="checkbox"]:checked + label::after {
  content: "✓";
  color: white;
  display: block;
  text-align: center;
  line-height: 20px;
}

7. 标签页切换

/* 标签项 */
.tab-item {
  padding: 10px 20px;
  background: #f5f5f5;
  cursor: pointer;
}

/* 激活状态 */
.tab-item:target {
  background: #fff;
  border-bottom: 2px solid #3498db;
  color: #3498db;
}

8. 图片画廊

/* 图片容器 */
.gallery-item {
  position: relative;
  overflow: hidden;
}

/* 悬停显示遮罩 */
.gallery-item:hover::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.gallery-item:hover::before {
  opacity: 1;
}

实战案例

案例1: 选项卡组件

/* 选项卡按钮 */
.tab-btn {
  padding: 10px 20px;
  background: #f5f5f5;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
}

.tab-btn:hover {
  background: #e0e0e0;
}

.tab-btn:active {
  background: #d0d0d0;
}

.tab-btn:focus {
  outline: 2px solid #3498db;
}

案例2: 表单样式

/* 表单组 */
.form-group {
  margin-bottom: 20px;
}

.form-group label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

.form-group input {
  width: 100%;
  padding: 10px;
  border: 2px solid #ddd;
  border-radius: 4px;
  transition: border-color 0.3s ease;
}

/* 焦点状态 */
.form-group input:focus {
  border-color: #3498db;
  outline: none;
  box-shadow: 0 0 5px rgba(52, 152, 219, 0.3);
}

/* 验证状态 */
.form-group input:valid {
  border-color: #27ae60;
}

.form-group input:invalid:not(:placeholder-shown) {
  border-color: #e74c3c;
}

/* 禁用状态 */
.form-group input:disabled {
  background-color: #f5f5f5;
  cursor: not-allowed;
}

案例3: 产品列表

/* 产品卡片 */
.product-card {
  padding: 20px;
  background: #fff;
  border-radius: 10px;
  transition: all 0.3s ease;
}

.product-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}

.product-card:active {
  transform: translateY(-2px);
}

/* 产品标题 */
.product-card h3 {
  font-size: 18px;
  margin-bottom: 10px;
}

/* 产品描述 */
.product-card p {
  color: #666;
  line-height: 1.6;
  margin-bottom: 15px;
}

/* 按钮样式 */
.product-card .btn {
  display: inline-block;
  padding: 8px 20px;
  background: #3498db;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: background 0.3s ease;
}

.product-card .btn:hover {
  background: #2980b9;
}

.product-card .btn:focus {
  outline: 2px solid #2980b9;
}

案例4: 新闻列表

/* 新闻项 */
.news-item {
  padding: 20px;
  border-bottom: 1px solid #eee;
  transition: background 0.3s ease;
}

.news-item:hover {
  background: #f9f9f9;
}

/* 第一个新闻项 */
.news-item:first-child {
  border-top: 1px solid #eee;
}

/* 最后一个新闻项 */
.news-item:last-child {
  border-bottom: none;
}

/* 新闻标题 */
.news-item h3 {
  font-size: 20px;
  margin-bottom: 10px;
}

.news-item h3 a {
  color: #333;
  transition: color 0.3s ease;
}

.news-item h3 a:hover {
  color: #3498db;
}

.news-item h3 a:active {
  color: #2980b9;
}

注意事项

  1. 链接伪类顺序: 必须按 LVHA 顺序声明
  2. 权重相同: 伪类权重都是 10,与类选择器相同
  3. 兼容性: 部分新伪类在旧浏览器中不支持
  4. 性能: 复杂的伪类选择器可能影响性能
  5. 可读性: 过度使用伪类会降低代码可读性

最佳实践

  1. 合理使用: 只在需要时使用伪类
  2. 性能优化: 避免过度复杂的伪类选择器
  3. 渐进增强: 提供回退方案
  4. 代码注释: 复杂伪类添加注释
  5. 测试兼容性: 浏览器兼容性测试
  6. 组合使用: 与其他选择器配合使用
  7. 交互反馈: 提供良好的用户反馈
  8. 可访问性: 考虑键盘导航和屏幕阅读器

总结

伪类选择器是 CSS 中非常强大的功能,能够根据元素的不同状态应用样式。掌握各种伪类的使用方法,可以帮助我们创建更丰富、更交互的网页效果。在实际开发中,要合理使用伪类,确保代码的可维护性和性能。