在CSS样式开发中,我们经常需要根据子元素的属性特征或者状态来设置不同的样式,传统的做法是为不同状态的子元素添加额外的类名,但是这样会增加HTML结构的复杂度。而结合CSS属性选择器和伪类选择器,就可以在不修改HTML结构的前提下,实现灵活的子元素样式控制。

CSS属性选择器基础语法
CSS属性选择器可以根据元素的属性及属性值来匹配元素,常用的语法有以下几种:
[attr]:匹配带有指定属性attr的元素[attr=value]:匹配属性attr的值为value的元素[attr^=value]:匹配属性attr的值以value开头的元素[attr$=value]:匹配属性attr的值以value结尾的元素[attr*=value]:匹配属性attr的值包含value的元素
比如我们要选择所有带有data-type属性的li元素,可以写成li[data-type],如果要选择data-type值为active的li元素,可以写成li[data-type="active"]。
CSS伪类选择器基础语法
伪类选择器用于选择处于特定状态的元素,针对子元素样式控制常用的伪类有以下几种:
:first-child:选择父元素下的第一个子元素:last-child:选择父元素下的最后一个子元素:nth-child(n):选择父元素下的第n个子元素,n可以是数字、关键词(even、odd)或者公式:not(selector):选择不符合指定选择器的元素:hover:选择鼠标悬停状态的元素
例如要选择列表中的奇数项li元素,可以写成li:nth-child(odd),要选择不是第一个子元素的li,可以写成li:not(:first-child)。
二者结合实现子元素样式控制
场景一:根据属性值调整特定位置子元素样式
假设我们有一个商品列表,每个商品项都有data-status属性表示商品状态,值为on表示上架,off表示下架,我们需要给第一个上架的商品添加特殊边框。
HTML结构如下:
<ul class="goods-list"> <li class="goods-item" data-status="off">商品1(下架)</li> <li class="goods-item" data-status="on">商品2(上架)</li> <li class="goods-item" data-status="on">商品3(上架)</li> <li class="goods-item" data-status="off">商品4(下架)</li> </ul>
对应的CSS代码如下:
/* 选择第一个data-status为on的li元素 */
.goods-list li[data-status="on"]:nth-child(-n+4) {
border: 2px solid #ff4d4f;
padding: 10px;
margin-bottom: 8px;
list-style: none;
}
/* 排除第一个上架商品之外的上架商品样式 */
.goods-list li[data-status="on"]:not(:first-child) {
border: 1px solid #d9d9d9;
padding: 10px;
margin-bottom: 8px;
list-style: none;
}
/* 下架商品样式 */
.goods-list li[data-status="off"] {
color: #999;
padding: 10px;
margin-bottom: 8px;
list-style: none;
text-decoration: line-through;
}
场景二:鼠标悬停时匹配特定属性子元素
如果我们需要在鼠标悬停到列表容器时,给所有带有data-tag属性且值包含hot的子元素添加背景色,可以这样实现:
HTML结构如下:
<div class="tag-list"> <span class="tag" data-tag="hot_new">热门新款</span> <span class="tag" data-tag="normal">普通商品</span> <span class="tag" data-tag="hot_sale">热门促销</span> <span class="tag" data-tag="old">老旧商品</span> </div>
对应的CSS代码如下:
.tag-list {
padding: 20px;
border: 1px solid #eee;
}
.tag {
display: inline-block;
padding: 6px 12px;
margin-right: 10px;
border-radius: 4px;
background-color: #f5f5f5;
}
/* 鼠标悬停到容器时,匹配data-tag包含hot的span元素 */
.tag-list:hover span[data-tag*="hot"] {
background-color: #fff7e6;
color: #fa8c16;
cursor: pointer;
}
场景三:按属性值分组控制奇偶子元素
当子元素有不同属性值时,我们可以结合:nth-child实现分组内的奇偶样式控制。比如下面的消息列表,data-type为system的是系统消息,user的是用户消息,我们给系统消息的奇数项添加浅蓝背景,偶数项添加白色背景。
HTML结构如下:
<div class="message-list"> <div class="message" data-type="system">系统消息1</div> <div class="message" data-type="user">用户消息1</div> <div class="message" data-type="system">系统消息2</div> <div class="message" data-type="user">用户消息2</div> <div class="message" data-type="system">系统消息3</div> </div>
对应的CSS代码如下:
.message {
padding: 12px;
margin-bottom: 8px;
border-radius: 4px;
}
/* 系统消息奇数项 */
.message[data-type="system"]:nth-child(odd) {
background-color: #e6f7ff;
}
/* 系统消息偶数项 */
.message[data-type="system"]:nth-child(even) {
background-color: #ffffff;
border: 1px solid #e6f7ff;
}
/* 用户消息统一样式 */
.message[data-type="user"] {
background-color: #f6ffed;
}
注意事项
- 属性选择器的属性值如果是字符串,需要加英文双引号,避免语法错误
- 伪类选择器的
nth-child计数是基于父元素下所有子元素的顺序,而不是仅匹配前面选择器筛选后的元素,使用时需要注意计数逻辑 - 二者结合时优先级会比单一选择器更高,如果需要覆盖样式需要调整选择器权重
- 避免过度嵌套复杂的选择器组合,否则会影响样式可读性和渲染性能