CSS 嵌套

介绍

CSS 嵌套是 CSS 中的一项新特性,它允许开发者在一个选择器内部嵌套另一个选择器,从而创建更加模块化、组织良好的 CSS 代码。这一特性消除了重复选择器的需要,使 CSS 结构更加清晰,更接近 HTML 的层次结构。在本章中,我们将探讨 CSS 嵌套的工作原理、语法规则以及如何在实际项目中有效使用它。

核心知识点

CSS 嵌套基础

1. 基本嵌套语法

  • 使用 & 符号引用父选择器
  • 可以在任何选择器内部嵌套其他选择器
  • 嵌套层级没有严格限制,但应保持合理以确保可读性

2. 父选择器引用

  • & 符号:引用父选择器的完整选择器链
  • 可用于创建伪类和伪元素的组合
  • 可用于创建选择器的变体和修饰符

3. 嵌套规则

  • 嵌套选择器继承父选择器的上下文
  • 嵌套选择器按层次结构组合
  • 嵌套可以包含任何有效的 CSS 规则

CSS 嵌套高级特性

1. 多层嵌套

  • 可以创建多层嵌套结构
  • 每层嵌套都会继承上层的选择器上下文
  • 应避免过度嵌套以保持代码可读性

2. 组合器嵌套

  • 可以在嵌套中使用后代、子元素、相邻兄弟和通用兄弟组合器
  • 组合器可以放在嵌套选择器的开头
  • 可以创建复杂的选择器关系

3. 媒体查询嵌套

  • 可以在选择器内部嵌套媒体查询
  • 媒体查询会继承父选择器的上下文
  • 允许为特定组件创建组件级别的响应式样式

4. 条件规则嵌套

  • 除了媒体查询,还可以嵌套其他条件规则
  • @supports@layer
  • 保持相关样式的逻辑分组

实用示例

示例 1:基本嵌套

/* 传统 CSS */
.navbar {
  background-color: #333;
  color: white;
  padding: 1rem;
}

.navbar .nav-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
}

.navbar .nav-item {
  margin-right: 1rem;
}

.navbar .nav-link {
  color: white;
  text-decoration: none;
  padding: 0.5rem;
  border-radius: 4px;
}

.navbar .nav-link:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

/* 使用嵌套的 CSS */
.navbar {
  background-color: #333;
  color: white;
  padding: 1rem;
  
  .nav-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
  }
  
  .nav-item {
    margin-right: 1rem;
  }
  
  .nav-link {
    color: white;
    text-decoration: none;
    padding: 0.5rem;
    border-radius: 4px;
    
    &:hover {
      background-color: rgba(255, 255, 255, 0.1);
    }
  }
}

示例 2:使用 & 引用父选择器

/* 使用 & 引用父选择器 */
.button {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 4px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.3s ease;
  
  &--primary {
    background-color: #3498db;
    color: white;
    
    &:hover {
      background-color: #2980b9;
    }
  }
  
  &--secondary {
    background-color: #95a5a6;
    color: white;
    
    &:hover {
      background-color: #7f8c8d;
    }
  }
  
  &--large {
    font-size: 1.25rem;
    padding: 1rem 2rem;
  }
  
  &--small {
    font-size: 0.875rem;
    padding: 0.5rem 1rem;
  }
}

/* 生成的 CSS */
.button {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 4px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.button--primary {
  background-color: #3498db;
  color: white;
}

.button--primary:hover {
  background-color: #2980b9;
}

.button--secondary {
  background-color: #95a5a6;
  color: white;
}

.button--secondary:hover {
  background-color: #7f8c8d;
}

.button--large {
  font-size: 1.25rem;
  padding: 1rem 2rem;
}

.button--small {
  font-size: 0.875rem;
  padding: 0.5rem 1rem;
}

示例 3:组合器嵌套

/* 组合器嵌套 */
.card {
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
  
  > .card-image {
    width: 100%;
    height: 200px;
    object-fit: cover;
  }
  
  > .card-content {
    padding: 1rem;
    
    h3 {
      margin-top: 0;
      color: #333;
    }
    
    p {
      color: #666;
      line-height: 1.5;
    }
    
    + .card-footer {
      padding: 1rem;
      background-color: #f8f9fa;
      border-top: 1px solid #ddd;
      
      button {
        background-color: #3498db;
        color: white;
        border: none;
        padding: 0.5rem 1rem;
        border-radius: 4px;
        cursor: pointer;
      }
    }
  }
}

示例 4:媒体查询嵌套

/* 媒体查询嵌套 */
.card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 1rem;
  margin-bottom: 1rem;
  
  .card-title {
    font-size: 1.25rem;
    margin-bottom: 0.5rem;
  }
  
  .card-content {
    font-size: 1rem;
    line-height: 1.5;
  }
  
  /* 嵌套媒体查询 */
  @media (min-width: 768px) {
    display: flex;
    gap: 1rem;
    padding: 1.5rem;
    
    .card-image {
      flex-shrink: 0;
      width: 150px;
      height: 150px;
      object-fit: cover;
      border-radius: 4px;
    }
    
    .card-body {
      flex: 1;
    }
    
    .card-title {
      font-size: 1.5rem;
    }
  }
  
  @media (min-width: 1024px) {
    padding: 2rem;
    gap: 1.5rem;
    
    .card-image {
      width: 200px;
      height: 200px;
    }
  }
}

示例 5:复杂嵌套结构

/* 复杂嵌套结构 */
.header {
  background-color: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  padding: 1rem 0;
  
  .container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    
    .logo {
      font-size: 1.5rem;
      font-weight: bold;
      color: #3498db;
      text-decoration: none;
    }
    
    .nav {
      display: flex;
      gap: 1.5rem;
      
      .nav-item {
        list-style: none;
        
        .nav-link {
          color: #333;
          text-decoration: none;
          font-weight: 500;
          transition: color 0.3s ease;
          
          &:hover {
            color: #3498db;
          }
          
          &.active {
            color: #3498db;
            border-bottom: 2px solid #3498db;
            padding-bottom: 0.25rem;
          }
        }
      }
    }
    
    .cta-button {
      background-color: #3498db;
      color: white;
      padding: 0.5rem 1rem;
      border-radius: 4px;
      text-decoration: none;
      font-weight: 500;
      transition: background-color 0.3s ease;
      
      &:hover {
        background-color: #2980b9;
      }
    }
  }
  
  /* 响应式设计 */
  @media (max-width: 768px) {
    .container {
      flex-direction: column;
      gap: 1rem;
      
      .nav {
        flex-wrap: wrap;
        justify-content: center;
        gap: 1rem;
      }
    }
  }
}

示例 6:使用 @supports 嵌套

/* 使用 @supports 嵌套 */
.gradient-card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 2rem;
  text-align: center;
  
  h2 {
    font-size: 1.5rem;
    margin-bottom: 1rem;
  }
  
  p {
    color: #666;
    line-height: 1.5;
  }
  
  /* 嵌套 @supports 规则 */
  @supports (background: linear-gradient(to right, #3498db, #2ecc71)) {
    background: linear-gradient(to right, #3498db, #2ecc71);
    color: white;
    
    p {
      color: rgba(255, 255, 255, 0.9);
    }
  }
}

实践练习

练习 1:创建嵌套导航组件

创建一个导航组件,具有以下特点:

  • 使用嵌套组织导航的不同部分(logo、菜单项、登录/注册按钮)
  • 为菜单项创建悬停和活动状态
  • 使用媒体查询嵌套创建响应式导航
  • 在移动设备上转换为汉堡菜单

练习 2:创建卡片组件系统

创建一个卡片组件系统,具有以下特点:

  • 使用嵌套创建基本卡片结构
  • 创建不同的卡片变体(默认、特色、紧凑)
  • 为卡片添加悬停效果
  • 使用媒体查询嵌套为不同屏幕尺寸优化卡片布局

练习 3:创建响应式表单

创建一个响应式表单,具有以下特点:

  • 使用嵌套组织表单元素
  • 为输入字段创建不同状态(默认、聚焦、错误)
  • 使用媒体查询嵌套在不同屏幕尺寸上调整表单布局
  • 添加表单验证样式

总结

在本章中,我们探讨了 CSS 嵌套,这是一项使 CSS 代码更加模块化和组织良好的重要特性。我们涵盖了:

  1. CSS 嵌套的基础知识,包括基本语法和父选择器引用
  2. 多层嵌套和组合器嵌套等高级特性
  3. 媒体查询和其他条件规则的嵌套
  4. 实际应用示例,如导航组件、卡片系统和响应式表单

CSS 嵌套通过消除重复选择器和创建更接近 HTML 结构的 CSS 代码,使 CSS 更加易于维护和理解。它允许开发者创建更加模块化的组件样式,并通过媒体查询嵌套实现组件级别的响应式设计。

然而,重要的是要使用嵌套适度,避免过度嵌套导致代码难以理解。保持合理的嵌套层级,并确保代码结构清晰,将有助于充分发挥 CSS 嵌套的优势。

复习问题

  1. CSS 嵌套的主要优势是什么?
  2. 如何在嵌套中引用父选择器?
  3. CSS 嵌套的基本语法是什么?
  4. 如何在嵌套中使用媒体查询?
  5. 什么是组合器嵌套?如何使用它?
  6. 如何避免过度嵌套的问题?
  7. CSS 嵌套如何改善代码组织?
  8. 如何使用嵌套创建组件变体?

进一步阅读

« 上一篇 CSS 容器查询 下一篇 » CSS 层叠上下文和堆叠顺序