组合选择器

组合选择器通过选择器之间的关系来选择元素,它们能够让我们更精确地定位目标元素。掌握组合选择器对于编写高效的 CSS 样式至关重要。

后代选择器

后代选择器(也称为包含选择器)选择某个元素的所有后代元素,无论嵌套多深。

语法

祖先元素 后代元素 {
  属性: 值;
}

基本用法

/* 选择所有 div 内的段落元素 */
div p {
  margin-bottom: 15px;
  line-height: 1.6;
}

/* 选择所有 nav 内的链接元素 */
nav a {
  color: white;
  text-decoration: none;
}

/* 选择所有 article 内的标题元素 */
article h1, article h2, article h3 {
  color: #2c3e50;
  margin-bottom: 15px;
}

实际应用

/* 导航栏样式 */
.main-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.main-nav ul li {
  display: inline-block;
  margin-right: 20px;
}

.main-nav ul li a {
  color: white;
  text-decoration: none;
  padding: 10px 15px;
  display: block;
}

.main-nav ul li a:hover {
  background: rgba(255,255,255,0.1);
}

/* 文章样式 */
.article p {
  line-height: 1.8;
  margin-bottom: 15px;
  color: #555;
}

.article img {
  max-width: 100%;
  height: auto;
  margin: 20px 0;
}

.article blockquote {
  border-left: 4px solid #3498db;
  padding-left: 20px;
  margin: 20px 0;
  color: #666;
  font-style: italic;
}

使用场景

后代选择器适用于以下情况:

  1. 组件内部样式:为组件内部的元素设置样式
  2. 布局区域样式:为特定区域内的元素统一样式
  3. 嵌套元素样式:处理多层嵌套的元素

注意事项

后代选择器会匹配所有后代元素,可能导致意外的样式应用:

/* 这会影响 div 内的所有段落,无论嵌套多深 */
div p {
  color: blue;
}

/* HTML 结构 */
<div>
  <p>直接子段落</p>
  <div>
    <p>嵌套段落</p>
  </div>
</div>

/* 两个段落都会被选中 */

子元素选择器

子元素选择器只选择某个元素的直接子元素,不包括更深层的后代元素。

语法

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

基本用法

/* 只选择 ul 的直接子元素 li */
ul > li {
  margin-bottom: 10px;
}

/* 只选择 nav 的直接子元素 a */
nav > a {
  font-weight: bold;
  text-transform: uppercase;
}

/* 只选择 table 的直接子元素 tbody */
table > tbody {
  background: #f5f5f5;
}

实际应用

/* 导航菜单 */
.nav-menu > li {
  display: inline-block;
  position: relative;
}

.nav-menu > li > a {
  display: block;
  padding: 15px 20px;
  color: white;
  text-decoration: none;
}

.nav-menu > li > a:hover {
  background: #555;
}

/* 下拉菜单 */
.dropdown > .dropdown-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  background: white;
  min-width: 200px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

.dropdown:hover > .dropdown-menu {
  display: block;
}

/* 卡片容器 */
.card-group > .card {
  display: inline-block;
  vertical-align: top;
  width: calc(33.333% - 20px);
  margin: 10px;
}

使用场景

子元素选择器适用于以下情况:

  1. 直接子元素样式:只影响直接子元素
  2. 避免样式污染:防止样式影响到深层嵌套元素
  3. 精确控制:更精确地选择目标元素

与后代选择器的区别

/* 后代选择器 - 选中所有后代 */
div p {
  color: blue;
}

/* 子元素选择器 - 只选中直接子元素 */
div > p {
  color: red;
}

/* HTML 结构 */
<div>
  <p>直接子段落(红色)</p>
  <div>
    <p>嵌套段落(蓝色)</p>
  </div>
</div>

相邻兄弟选择器

相邻兄弟选择器选择紧接在某个元素之后的兄弟元素,两者必须有相同的父元素。

语法

元素1 + 元素2 {
  属性: 值;
}

基本用法

/* 选择紧接在 h1 之后的段落 */
h1 + p {
  font-size: 18px;
  font-weight: bold;
  color: #333;
}

/* 选择紧接在 li 之后的 li */
li + li {
  margin-top: 10px;
}

/* 选择紧接在 .title 之后的 .content */
.title + .content {
  padding-top: 20px;
  border-top: 1px solid #ddd;
}

实际应用

/* 文章排版 */
.article h2 + p {
  margin-top: 0;
  font-weight: bold;
}

/* 列表样式 */
.features-list li + li {
  margin-top: 15px;
}

.features-list li + li::before {
  content: "→ ";
  color: #3498db;
}

/* 表单样式 */
.form-group + .form-group {
  margin-top: 20px;
}

.form-group label + input {
  margin-top: 5px;
}

/* 卡片列表 */
.card + .card {
  margin-top: 20px;
}

使用场景

相邻兄弟选择器适用于以下情况:

  1. 元素间距:为相邻元素设置间距
  2. 特殊样式:为特定位置的元素设置特殊样式
  3. 分隔线:在元素之间添加分隔线

注意事项

相邻兄弟选择器只选择紧接在后面的第一个兄弟元素:

/* 只选择第一个相邻的 li */
li + li {
  margin-top: 10px;
}

/* HTML 结构 */
<ul>
  <li>项目 1</li>
  <li>项目 2 - 有上边距</li>
  <li>项目 3 - 有上边距</li>
  <li>项目 4 - 有上边距</li>
</ul>

通用兄弟选择器

通用兄弟选择器选择某个元素之后的所有兄弟元素。

语法

元素1 ~ 元素2 {
  属性: 值;
}

基本用法

/* 选择 h1 之后的所有段落 */
h1 ~ p {
  color: #666;
}

/* 选择 .active 之后的所有列表项 */
.active ~ li {
  opacity: 0.7;
}

/* 选择 input 之后的所有 label */
input ~ label {
  margin-left: 10px;
}

实际应用

/* 表单反馈 */
input:focus ~ .hint {
  display: block;
  color: #666;
  font-size: 14px;
}

input:valid ~ .success-icon {
  display: inline-block;
  color: #28a745;
}

input:invalid ~ .error-icon {
  display: inline-block;
  color: #dc3545;
}

/* 选项卡 */
.tab:checked ~ .tab-content {
  display: block;
}

.tab-content {
  display: none;
}

/* 图片画廊 */
img:hover ~ figcaption {
  opacity: 1;
}

使用场景

通用兄弟选择器适用于以下情况:

  1. 表单验证:根据输入状态显示提示
  2. 选项卡切换:实现纯 CSS 的选项卡
  3. 交互效果:基于元素状态的样式变化

组合选择器的优先级

组合选择器的优先级计算是将所有选择器的优先级相加:

/* 优先级:0,0,2 */
div p {
  color: blue;
}

/* 优先级:0,1,1 */
div .text {
  color: green;
}

/* 优先级:0,2,0 */
.text1 + .text2 {
  color: red;
}

组合选择器的性能

不同的组合选择器对性能的影响不同:

性能从高到低

  1. 子元素选择器 - 较快
  2. 相邻兄弟选择器 - 中等
  3. 通用兄弟选择器 - 较慢
  4. 后代选择器 - 最慢

性能优化建议

/* 不推荐 - 过度嵌套 */
body div.container div.content div.article div.title h1 {
  font-size: 24px;
}

/* 推荐 - 使用类选择器 */
.article-title {
  font-size: 24px;
}

/* 不推荐 - 深层后代选择器 */
.main-nav ul li a span {
  color: white;
}

/* 推荐 - 使用类选择器 */
.nav-link-text {
  color: white;
}

实际项目中的应用

网站导航

/* 导航容器 */
.main-nav {
  background: #2c3e50;
  padding: 0 20px;
}

/* 导航列表 */
.main-nav > ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* 导航项 */
.main-nav > ul > li {
  display: inline-block;
  position: relative;
}

/* 导航链接 */
.main-nav > ul > li > a {
  display: block;
  padding: 15px 20px;
  color: white;
  text-decoration: none;
}

/* 导航链接悬停 */
.main-nav > ul > li > a:hover {
  background: #34495e;
}

/* 下拉菜单 */
.main-nav > ul > li > ul {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  background: #34495e;
  min-width: 200px;
}

/* 下拉菜单项 */
.main-nav > ul > li > ul > li {
  display: block;
}

/* 下拉菜单链接 */
.main-nav > ul > li > ul > li > a {
  padding: 12px 20px;
  display: block;
  color: white;
  text-decoration: none;
}

/* 显示下拉菜单 */
.main-nav > ul > li:hover > ul {
  display: block;
}

文章内容

/* 文章容器 */
.article {
  max-width: 800px;
  margin: 0 auto;
  padding: 40px 20px;
}

/* 文章标题 */
.article h1 {
  font-size: 32px;
  color: #2c3e50;
  margin-bottom: 20px;
}

/* 文章元信息 */
.article h1 + .meta {
  color: #666;
  font-size: 14px;
  margin-bottom: 30px;
}

/* 文章内容 */
.article > p {
  line-height: 1.8;
  margin-bottom: 20px;
  color: #555;
}

/* 文章中的标题 */
.article > h2 {
  font-size: 24px;
  color: #34495e;
  margin-top: 40px;
  margin-bottom: 15px;
}

/* 文章中的列表 */
.article > ul {
  margin: 20px 0;
  padding-left: 30px;
}

/* 文章中的列表项 */
.article > ul > li {
  margin-bottom: 10px;
}

/* 文章中的代码块 */
.article > pre {
  background: #f5f5f5;
  padding: 15px;
  border-radius: 4px;
  overflow-x: auto;
  margin: 20px 0;
}

/* 文章中的图片 */
.article > img {
  max-width: 100%;
  height: auto;
  margin: 30px 0;
}

总结

组合选择器让我们能够更精确地选择元素,是编写高效 CSS 的重要工具:

  1. 后代选择器:选择所有后代元素,使用空格分隔
  2. 子元素选择器:只选择直接子元素,使用 > 分隔
  3. 相邻兄弟选择器:选择紧接的兄弟元素,使用 + 分隔
  4. 通用兄弟选择器:选择所有后续兄弟元素,使用 ~ 分隔

记住以下几点:

  • 理解不同组合选择器的区别和应用场景
  • 子元素选择器比后代选择器更精确
  • 避免过度嵌套选择器,影响性能
  • 优先使用类选择器,减少对组合选择器的依赖
  • 合理使用组合选择器可以提高代码的可读性和可维护性

在接下来的章节中,我们将学习属性选择器、伪类选择器和伪元素选择器,进一步提高选择 CSS 元素的能力。