子代选择器

学习

子代选择器

2026-02-23/0/ 编辑


子代选择器

概述

子代选择器(也称为直接子选择器)用于选择某个元素的直接子元素,只匹配第一层后代元素。

语法

父元素 > 子元素 {
  属性: 值;
}

注意: 父元素和子元素之间用大于号 > 分隔,并且要有空格。

基本示例

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 {
  /* ... */
}

最佳实践

  1. 精确控制: 当只需要直接子元素时使用子代选择器
  2. 性能优化: 相比后代选择器,子代选择器性能更好
  3. 避免过度嵌套: 层级不宜过深
  4. 配合类名使用: 结合类名提高可读性
  5. 合理选择: 根据实际需求选择子代选择器或后代选择器

总结

子代选择器是 CSS 中非常实用的选择器,能够精确选择直接子元素,避免样式影响嵌套元素。理解子代选择器与后代选择器的区别,并在合适的场景中使用,能够提高代码的可维护性和性能。