CSS 伪类选择器
CSS 伪类是一种用于选择元素特定状态或位置的关键字,它们可以为现有元素添加特殊效果,而无需在 HTML 中添加新的类或 ID。
通过伪类,开发者能够基于用户交互(如鼠标悬停)、元素在文档树中的位置(如第一个子元素)、或特定属性(如已访问链接)等条件来应用样式,极大地增强了 CSS 的选择能力和灵活性。
1. 什么是伪类?
伪类以冒号 : 开头,并附加到选择器后面,用于指定元素的特殊状态或位置。它们允许你根据元素在某个时刻或某个上下文中的情况来应用样式,而不是仅仅基于其在文档结构中的标签名、类或ID。理解伪类对于创建交互式和动态的网页至关重要。
1.1 伪类的作用
- 响应用户交互: 例如,当用户将鼠标悬停在链接上时改变其颜色。
- 基于元素状态: 根据表单输入字段是启用、禁用还是被选中来改变其样式。
- 基于元素位置: 选择一个列表中第一个或最后一个项目,或者选择特定类型的Nth个子元素。
- 基于文档结构: 应用样式到链接的已访问或未访问状态。
2. 常用伪类分类与示例
CSS 伪类可以根据其功能大致分为几类,每类都服务于不同的样式需求。
2.1 动态伪类 (User Action Pseudo-classes)
这些伪类响应用户与元素的交互。
- :link
- 描述: 选择所有未被访问的
<a>元素。
a:link {
color: blue;
}- :visited
- 描述: 选择所有已被访问的
<a>元素。出于隐私考虑,可样式化的属性受到严格限制(通常只能改变color)。
a:visited {
color: purple;
}- :hover
- 描述: 选择鼠标指针悬停在其上的元素。
button:hover {
background-color: lightgray;
}- :active
- 描述: 选择被用户激活(例如,点击鼠标时)的元素。
button:active {
background-color: darkgray;
transform: translateY(1px);
}- :focus
- 描述: 选择当前获得焦点的元素(通常是表单元素或链接)。
input:focus {
border: 2px solid blue;
outline: none; /* 移除浏览器默认的焦点轮廓 */
}注意: 动态伪类的顺序很重要,通常遵循 LVHA 顺序(Link, Visited, Hover, Active)以确保所有状态都能正确应用。
2.2 UI 元素状态伪类 (UI Element States Pseudo-classes)
这些伪类选择处于特定 UI 状态的元素,常用于表单元素。
- :enabled
- 描述: 选择所有已启用的表单元素。
input:enabled {
background-color: white;
}- :disabled
- 描述: 选择所有被禁用的表单元素。
input:disabled {
background-color: #eee;
cursor: not-allowed;
}- :checked
- 描述: 选择所有被选中的
radio、checkbox或option元素。
input[type="checkbox"]:checked + label {
font-weight: bold;
}- :read-only
- 描述: 选择设置了
readonly属性的输入字段。
input:read-only {
background-color: #f0f0f0;
border-color: #ccc;
}- :read-write
- 描述: 选择用户可编辑的输入字段。
input:read-write {
border: 1px solid blue;
}- :valid
- 描述: 选择内容通过验证的
input或form元素。
input:valid {
border-color: green;
}- :invalid
- 描述: 选择内容未通过验证的
input或form元素。
input:invalid {
border-color: red;
}2.3 结构性伪类 (Structural Pseudo-classes)
这些伪类根据元素在文档树中的位置来选择元素。
- :first-child
- 描述: 选择父元素的第一个子元素。
ul li:first-child {
font-weight: bold;
}- :last-child
- 描述: 选择父元素的最后一个子元素。
ul li:last-child {
border-bottom: none;
}- :nth-child(n)
- 描述: 选择父元素的第
n个子元素。n可以是数字、关键字(even,odd)或公式(An+B)。
tr:nth-child(even) { /* 选择偶数行 */
background-color: #f2f2f2;
}
p:nth-child(3n+1) { /* 选择第1, 4, 7...个p元素 */
color: green;
}- :nth-last-child(n)
- 描述: 从父元素的最后一个子元素开始倒数,选择第
n个子元素。
li:nth-last-child(2) { /* 选择倒数第二个li */
text-decoration: underline;
}- :first-of-type
- 描述: 选择其父元素的指定类型的第一个子元素。
div p:first-of-type { /* 选择div内的第一个p元素 */
color: red;
}- :last-of-type
- 描述:选择其父元素的指定类型的最后一个子元素。
div p:last-of-type {
color: blue;
}- :nth-of-type(n)
- 描述: 选择其父元素的指定类型的第
n个子元素。
span:nth-of-type(2) { /* 选择父元素中第二个span */
font-style: italic;
}- :nth-last-of-type(n)
- 描述: 从其父元素的指定类型的最后一个子元素开始倒数,选择第
n个子元素。
img:nth-last-of-type(1) { /* 选择父元素中最后一个图片 */
border: 2px solid orange;
}- :only-child
- 描述: 选择是其父元素的唯一子元素的元素。
p:only-child {
background-color: yellow;
}- :only-of-type
- 描述: 选择是其父元素的指定类型的唯一子元素的元素。
div:only-of-type {
border: 1px dashed gray;
}- :empty
- 描述: 选择不包含任何子元素(包括文本节点)的元素。
div:empty {
height: 20px;
background-color: lightgray;
}- :root
- 描述: 选择文档的根元素(通常是
<html>)。
:root {
--main-color: #336699; /* 定义CSS变量 */
}- :not(selector)
- 描述: 选择不匹配括号内选择器的元素(否定伪类)。
li:not(.special) {
color: #333;
}- :has(selector) (CSS Selectors Level 4)
- 描述: 选择包含(或“拥有”)一个或多个选择器所匹配的元素的元素。
div:has(p) { /* 选择包含p元素的div */
border: 1px solid green;
}- :where(selector-list) (CSS Selectors Level 4)
- 描述: 接受一个选择器列表作为参数,并选择其中任意一个选择器匹配的元素,且优先级为 0。
:where(h1, h2, h3) {
margin-top: 0;
}- :is(selector-list) (CSS Selectors Level 4)
- 描述: 接受一个选择器列表作为参数,并选择其中任意一个选择器匹配的元素。其优先级由列表中最高优先级的选择器决定。
:is(h1, h2):hover {
color: blue;
}2.4 语言伪类 (Linguistic Pseudo-classes)
- :lang(language)
- 描述: 选择
lang属性设置为指定语言的元素。
p:lang(zh) {
font-family: 'Microsoft YaHei', sans-serif;
}
p:lang(en) {
font-family: Arial, sans-serif;
}2.5 时间轴伪类 (Time-dimensional Pseudo-classes)
这些伪类用于选择处于特定播放状态的媒体元素,如视频或音频。
- :playing
- 描述: 选择当前正在播放的媒体元素。
video:playing {
border: 2px solid green;
}- :paused
- 描述: 选择当前已暂停的媒体元素。
video:paused {
border: 2px solid red;
}3. 最佳实践与注意事项
- LVHA 顺序: 对于链接伪类(
:link,:visited,:hover,:active),始终遵循这个顺序来编写 CSS 规则,以确保所有状态都能正确应用。:active应该放在:hover之后,因为它代表一个更具体的、短暂的状态。 - 可访问性: 结合
:focus伪类提供清晰的焦点指示,这对于键盘用户至关重要。移除浏览器默认outline后,务必提供自定义的视觉焦点样式。 - 性能考量: 复杂的结构性伪类(如
nth-child配合复杂公式)在大型文档中可能会稍微影响性能,但对于大多数现代应用来说,这不是一个主要问题。 - 浏览器兼容性: 大多数伪类都有良好的浏览器支持。然而,一些较新的伪类(如
:has,:where,:is)可能在旧版本浏览器中不受支持,使用时需注意兼容性,或使用 Polyfill。 - 级联和特异性: 伪类的特异性(specificity)与普通类选择器相同。理解 CSS 级联规则对于解决样式冲突至关重要。
:not()的局限性::not()只能否定简单的选择器,不能否定复杂选择器列表,并且不能否定另一个not()。它也不会增加选择器的特异性。:checked与自定义表单::checked伪类在自定义radio或checkbox样式时非常有用,通常结合+(相邻兄弟选择器) 来改变相关联label的样式。
通过熟练运用这些 CSS 伪类,开发者能够创建出更加动态、交互丰富且易于维护的网页界面。它们是 CSS 强大选择能力的核心组成部分,使得样式可以根据元素的各种条件和状态进行细粒度控制。