子代选择器
概述
子代选择器(也称为直接子选择器)用于选择某个元素的直接子元素,只匹配第一层后代元素。
语法
父元素 > 子元素 {
属性: 值;
}注意: 父元素和子元素之间用大于号 > 分隔,并且要有空格。
基本示例
1. 直接子元素
/* 只选择 ul 的直接子元素 li */
ul > li {
padding: 10px;
background-color: #f5f5f5;
}<ul>
<li>直接子元素 1 - 会被选中</li>
<li>直接子元素 2 - 会被选中</li>
<li>
<ul>
<li>嵌套的子元素 1 - 不会被选中</li>
<li>嵌套的子元素 2 - 不会被选中</li>
</ul>
</li>
</ul>2. 多级选择
/* 选择 div > p > span */
div > p > span {
color: red;
}<div>
<p>
<span>这段文字是红色</span>
</p>
<div>
<p>
<span>这段文字也是红色</span>
</p>
</div>
</div>与后代选择器的区别
后代选择器(空格)
ul li {
/* 选择 ul 的所有后代 li 元素,包括嵌套的 */
padding: 10px;
}效果: 选择 ul 下所有的 li 元素,无论层级多深
子代选择器(>)
ul > li {
/* 只选择 ul 的直接子元素 li */
padding: 10px;
}效果: 只选择 ul 的直接子元素 li,不选择嵌套的 li
对比示例
/* 后代选择器 */
.menu a {
color: blue; /* 所有层级的链接都是蓝色 */
}
/* 子代选择器 */
.menu > a {
color: red; /* 只有第一层链接是红色 */
}<div class="menu">
<a href="#">第一层链接 - 红色</a>
<ul>
<li><a href="#">第二层链接 - 蓝色</a></li>
<li><a href="#">第二层链接 - 蓝色</a></li>
</ul>
</div>权重计算
子代选择器的权重是各组成部分权重之和:
div > p {
/* 权重 = 1(div) + 1(p) = 2 */
color: red;
}
ul > li.special {
/* 权重 = 1(ul) + 1(li) + 10(.special) = 12 */
color: blue;
}
.container > .box {
/* 权重 = 10(.container) + 10(.box) = 20 */
color: green;
}常见应用场景
1. 导航菜单
/* 一级导航 */
.nav > li {
display: inline-block;
margin-right: 20px;
}
.nav > li > a {
font-weight: bold;
font-size: 16px;
}
/* 二级导航(不需要 >,使用后代选择器) */
.nav li li a {
font-size: 14px;
color: #666;
}<ul class="nav">
<li>
<a href="#">首页</a>
</li>
<li>
<a href="#">产品</a>
<ul>
<li><a href="#">产品1</a></li>
<li><a href="#">产品2</a></li>
</ul>
</li>
</ul>2. 卡片布局
/* 直接子元素设置为弹性布局 */
.card-container > .card {
flex: 1;
margin: 10px;
}<div class="card-container">
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
</div>3. 表单分组
/* 表单容器的直接子元素 */
.form-group > input,
.form-group > select,
.form-group > textarea {
width: 100%;
padding: 10px;
}
.form-group > label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}<div class="form-group">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名">
</div>4. 清除特定元素的样式
/* 只对一级链接添加样式 */
.article > p > a:first-child {
color: red;
font-weight: bold;
}<div class="article">
<p>
<a href="#">这是第一段的第一行链接</a>
其他文本 <a href="#">其他链接</a>
</p>
<p>
<a href="#">这是第二段的第一行链接</a>
</p>
</div>5. 栅格系统
/* 栅格行 */
.row {
display: flex;
flex-wrap: wrap;
margin: 0 -15px;
}
/* 直接子元素列 */
.row > [class*="col-"] {
padding: 0 15px;
}
.row > .col-1 { flex: 0 0 8.333333%; max-width: 8.333333%; }
.row > .col-2 { flex: 0 0 16.666667%; max-width: 16.666667%; }
.row > .col-3 { flex: 0 0 25%; max-width: 25%; }
/* ... */<div class="row">
<div class="col-3">1/4</div>
<div class="col-6">1/2</div>
<div class="col-3">1/4</div>
</div>6. 列表样式
/* 只对顶级列表项添加图标 */
.list-group > li {
padding-left: 30px;
background: url(icon.png) no-repeat left center;
}
/* 嵌套列表不需要图标 */
.list-group li li {
padding-left: 20px;
background: none;
}7. 标题层次
/* 容器的直接子元素标题 */
.container > h1,
.container > h2,
.container > h3 {
margin-bottom: 20px;
border-bottom: 2px solid #eee;
padding-bottom: 10px;
}
/* 嵌套的标题不需要这些样式 */
.container h1 h2,
.container h2 h3 {
margin-bottom: 10px;
border-bottom: none;
}高级用法
1. 多个子代选择器组合
/* 多级直接子元素 */
.menu > li > a {
color: #333;
}
.menu > li > ul > li > a {
color: #666;
font-size: 14px;
}2. 与伪类配合
/* 第一个直接子元素 */
.container > .box:first-child {
margin-top: 0;
}
/* 最后一个直接子元素 */
.container > .box:last-child {
margin-bottom: 0;
}
/* 偶数位置的直接子元素 */
.row > .col:nth-child(even) {
background-color: #f9f9f9;
}3. 与属性选择器配合
/* 选择具有特定属性的直接子元素 */
.form > input[type="text"] {
width: 100%;
}
.form > input[type="email"] {
width: 100%;
}4. 与交集选择器配合
/* 同时满足多个条件的直接子元素 */
.container > .box.active {
border: 2px solid red;
}
.nav > li.current > a {
color: #ff6700;
}5. 多个父元素共享样式
/* 多个父元素的直接子元素 */
.header > a,
.footer > a {
color: #333;
}性能考虑
1. 子代选择器 vs 后代选择器
/* ❌ 后代选择器: 性能较差(需要遍历所有后代) */
.container a {
/* ... */
}
/* ✅ 子代选择器: 性能较好(只检查直接子元素) */
.container > a {
/* ... */
}2. 层级不宜过深
/* ❌ 不推荐: 层级过深,影响性能 */
body > div > div > div > ul > li > a {
/* ... */
}
/* ✅ 推荐: 使用类名简化 */
.nav-link {
/* ... */
}实战案例
案例1: 面包屑导航
/* 面包屑导航 */
.breadcrumb {
display: flex;
align-items: center;
padding: 10px 0;
}
.breadcrumb > li {
margin-right: 5px;
}
.breadcrumb > li:not(:last-child)::after {
content: ">";
margin-left: 5px;
color: #999;
}
.breadcrumb > li > a {
color: #3498db;
}
.breadcrumb > li:last-child {
color: #333;
font-weight: bold;
}<ul class="breadcrumb">
<li><a href="#">首页</a></li>
<li><a href="#">产品</a></li>
<li>手机</li>
</ul>案例2: 评论系统
/* 评论列表 */
.comment-list {
max-width: 800px;
margin: 0 auto;
}
/* 一级评论 */
.comment-list > .comment {
margin-bottom: 20px;
padding: 20px;
background: #fff;
border-left: 4px solid #3498db;
}
/* 二级回复(嵌套) */
.comment .comment {
margin-top: 15px;
background: #f9f9f9;
border-left-color: #95a5a6;
}
/* 三级回复 */
.comment .comment .comment {
border-left-color: #bdc3c7;
}<div class="comment-list">
<div class="comment">
<p>这是一条评论</p>
<div class="comment">
<p>这是回复1</p>
<div class="comment">
<p>这是回复2</p>
</div>
</div>
</div>
</div>案例3: 卡片网格
/* 卡片网格 */
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.card-grid > .card {
background: #fff;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
}
.card-grid > .card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(0,0,0,0.2);
}
.card > h3 {
margin-bottom: 10px;
color: #333;
}
.card > p {
color: #666;
line-height: 1.6;
}案例4: Flexbox 布局
/* Flex 容器 */
.flex-container {
display: flex;
justify-content: space-between;
align-items: center;
}
/* 直接子元素 */
.flex-container > .item {
padding: 10px;
background: #f5f5f5;
border-radius: 5px;
}
/* 第一个子元素 */
.flex-container > .item:first-child {
margin-right: 10px;
}
/* 最后一个子元素 */
.flex-container > .item:last-child {
margin-left: 10px;
}注意事项
1. 只选择直接子元素
.container > div {
/* 不会选择嵌套的 div */
}2. 空格很重要
/* ❌ 错误: 缺少空格 */
.container>div {}
/* ✅ 正确: 有空格 */
.container > div {}3. 兼容性
子代选择器在所有现代浏览器中都支持,包括:
- ✅ Chrome
- ✅ Firefox
- ✅ Safari
- ✅ Edge
- ✅ IE7+
4. 与后代选择器结合使用
/* 直接子元素 */
.container > .box {
/* ... */
}
/* 所有后代元素 */
.container .box {
/* ... */
}
/* 嵌套的直接子元素 */
.container > .box > .inner {
/* ... */
}最佳实践
- 精确控制: 当只需要直接子元素时使用子代选择器
- 性能优化: 相比后代选择器,子代选择器性能更好
- 避免过度嵌套: 层级不宜过深
- 配合类名使用: 结合类名提高可读性
- 合理选择: 根据实际需求选择子代选择器或后代选择器
总结
子代选择器是 CSS 中非常实用的选择器,能够精确选择直接子元素,避免样式影响嵌套元素。理解子代选择器与后代选择器的区别,并在合适的场景中使用,能够提高代码的可维护性和性能。