CSS中的伪类选择器和伪元素选择器代码分析
在CSS样式开发中,伪类选择器和伪元素选择器是两类非常实用的选择器,它们不需要依赖额外的HTML类名或ID,就能基于元素的状态、位置或者结构来添加样式,也可以创建不在DOM树中的虚拟元素。下面我们分别对这两类选择器进行详细的代码分析。
一、伪类选择器
伪类选择器用于选择处于特定状态的元素,通常以冒号:作为前缀,常见的包括动态伪类、结构伪类、表单相关伪类等。
1. 动态伪类选择器
动态伪类主要和元素的交互状态相关,比如鼠标悬停、元素获得焦点等,下面是一段常见的动态伪类使用示例:
/* 未访问过的链接样式 */
a:link {
color: #333;
text-decoration: none;
}
/* 访问过的链接样式 */
a:visited {
color: #999;
}
/* 鼠标悬停在链接上时的样式 */
a:hover {
color: #ff6600;
text-decoration: underline;
}
/* 链接被激活(鼠标按下未松开)时的样式 */
a:active {
color: #ff0000;
}
/* 输入框获得焦点时的样式 */
input:focus {
border: 2px solid #409eff;
outline: none;
}这段代码中,:link和:visited针对链接的不同访问状态设置样式,:hover和:active响应鼠标的交互行为,:focus则处理表单元素获得焦点的状态,这些伪类不需要我们手动修改元素的属性,浏览器会根据用户操作自动匹配对应的样式。
2. 结构伪类选择器
结构伪类主要根据元素在DOM树中的位置来选择,常用的有:first-child、:last-child、:nth-child()等,下面看一个列表样式的示例:
/* 选择ul下的第一个li子元素,设置红色文字 */
ul li:first-child {
color: #f00;
}
/* 选择ul下的最后一个li子元素,设置加粗 */
ul li:last-child {
font-weight: bold;
}
/* 选择ul下所有偶数位置的li子元素,设置浅灰色背景 */
ul li:nth-child(even) {
background-color: #f5f5f5;
}
/* 选择ul下所有奇数位置的li子元素,设置白色背景 */
ul li:nth-child(odd) {
background-color: #fff;
}
/* 选择div下第一个类型为p的子元素,不管前面有没有其他元素 */
div p:first-of-type {
font-size: 16px;
}这里:first-child和:last-child直接匹配父元素的首尾子元素,:nth-child()支持传入数值、even(偶数)、odd(奇数)或者公式(比如2n+1)来匹配对应位置的元素,:first-of-type则是匹配同类型元素中的第一个,和结构位置无关,只和元素类型相关。
3. 表单相关伪类
针对表单元素的状态,CSS也提供了对应的伪类,比如:checked、:disabled、:required等,示例代码如下:
/* 被选中的复选框后面的文字设置为绿色 */
input[type="checkbox"]:checked + span {
color: #67c23a;
}
/* 被禁用的输入框设置灰色背景和虚线边框 */
input:disabled {
background-color: #f5f5f5;
border: 1px dashed #ccc;
cursor: not-allowed;
}
/* 必填的输入框前面添加红色星号提示 */
input:required::before {
content: "*";
color: #f00;
}这些伪类可以直接根据表单元素的状态设置样式,不需要额外给元素添加类名标记状态,减少了HTML和CSS的耦合度。
二、伪元素选择器
伪元素选择器用于创建不在DOM树中的虚拟元素,通常以双冒号::作为前缀(CSS3规范,旧版单冒号也兼容),常见的包括::before、::after、::first-line、::first-letter等。
1. ::before和::after伪元素
这两个伪元素可以在选中元素的内容前面或后面插入虚拟内容,必须通过content属性来定义插入的内容,即使内容为空也需要写content: "",示例代码如下:
/* 在所有段落前面添加引号 */
p::before {
content: "“";
color: #999;
font-size: 20px;
margin-right: 5px;
}
/* 在所有段落后面添加引号 */
p::after {
content: "”";
color: #999;
font-size: 20px;
margin-left: 5px;
}
/* 给所有外部链接后面添加小图标提示 */
a[href^="http"]::after {
content: " ";
display: inline-block;
width: 12px;
height: 12px;
background: url("https://ipipp.com/link-icon.png") no-repeat center;
background-size: contain;
margin-left: 3px;
}
/* 用::after实现一个简单的清除浮动效果 */
.clearfix::after {
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
}这里::before和::after插入的内容不算真正的DOM节点,无法通过JavaScript直接操作,也不会影响页面的DOM结构,非常适合用来实现装饰性的效果,比如清除浮动、添加提示图标等。
2. ::first-line和::first-letter伪元素
这两个伪元素针对文本内容的首行和首字母设置样式,示例代码如下:
/* 文章段落的首行文字设置为加粗,颜色加深 */
.article p::first-line {
font-weight: bold;
color: #222;
}
/* 文章段落的首字母放大,下沉显示 */
.article p::first-letter {
font-size: 32px;
float: left;
line-height: 1;
margin-right: 5px;
color: #409eff;
}::first-line只能用于块级元素,匹配元素的第一行文本,当浏览器窗口大小变化导致第一行文本行数改变时,样式会自动匹配新的首行。::first-letter则匹配块级元素的第一个字母,常用来实现报刊类的首字母下沉效果。
三、伪类和伪元素的区别
虽然两者都带有冒号前缀,但核心区别很明显:
- 伪类选择器是选择已经存在的元素处于某种状态时的样式,不会影响DOM结构,只是匹配元素的不同状态。
- 伪元素选择器是创建不存在于DOM中的虚拟元素,并且可以给这个虚拟元素设置样式,相当于新增了一个看不见的节点。
- 在语法上,CSS3规范推荐伪类用单冒号
:,伪元素用双冒号::,不过部分旧版伪元素(比如:before、:after)的单冒号写法仍然被浏览器兼容。
合理使用伪类和伪元素选择器,可以让我们在不修改HTML结构的前提下实现很多样式效果,减少冗余的类名,让代码更简洁易维护。