CSS 嵌套与媒体查询:更优雅的样式组织

写在前面

今天想和你聊聊 CSS 中两个让样式组织更加优雅的特性——CSS 嵌套和媒体查询。在我眼里,它们就像是给 CSS 配上了"结构化思维",让我们能够以更符合直觉的方式编写样式。

作为一名把代码当散文写的 UI 匠人,我始终认为:好的代码应该像好的文章一样,有清晰的结构和层次。CSS 嵌套和媒体查询让我们能够实现这种结构化的表达方式。

CSS 嵌套:回归直觉的写法

什么是 CSS 嵌套?

CSS 嵌套允许我们在一个选择器内部定义其他选择器,就像我们在预处理器(如 Sass、Less)中习惯的那样。这让 CSS 代码更加直观和易于维护。

基本语法

/* 传统写法 */
.card { }
.card .card-title { }
.card .card-content { }
.card:hover { }

/* 嵌套写法 */
.card {
  background: white;
  border-radius: 8px;
  
  .card-title {
    font-size: 1.25rem;
    font-weight: 600;
  }
  
  .card-content {
    padding: 16px;
    line-height: 1.6;
  }
  
  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  }
}

& 符号的妙用

& 符号代表父选择器,让我们能够创建更复杂的选择器:

.button {
  padding: 12px 24px;
  background: #667eea;
  
  /* 伪类 */
  &:hover {
    background: #5a6fd8;
  }
  
  &:active {
    transform: scale(0.98);
  }
  
  /* 伪元素 */
  &::before {
    content: '';
    display: inline-block;
    margin-right: 8px;
  }
  
  /* 类组合 */
  &.primary {
    background: #667eea;
  }
  
  &.secondary {
    background: #764ba2;
  }
  
  /* 属性选择器 */
  &[disabled] {
    opacity: 0.5;
    cursor: not-allowed;
  }
}

媒体查询:响应式设计的基石

什么是媒体查询?

媒体查询让我们能够根据设备的特性(如屏幕宽度、高度、方向等)应用不同的样式。这是实现响应式设计的核心技术。

基本语法

/* 基础媒体查询 */
@media (max-width: 768px) {
  .container {
    padding: 16px;
  }
}

/* 多个条件 */
@media (min-width: 768px) and (max-width: 1024px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* 方向查询 */
@media (orientation: landscape) {
  .hero {
    height: 100vh;
  }
}

/* 深色模式 */
@media (prefers-color-scheme: dark) {
  body {
    background: #1a1a1a;
    color: #ffffff;
  }
}

嵌套与媒体查询的结合

在嵌套中使用媒体查询

.card {
  padding: 24px;
  
  @media (max-width: 768px) {
    padding: 16px;
  }
  
  .card-title {
    font-size: 1.5rem;
    
    @media (max-width: 768px) {
      font-size: 1.25rem;
    }
  }
}

实际应用示例

/* 响应式导航 */
.navbar {
  display: flex;
  align-items: center;
  padding: 16px 24px;
  background: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  
  .logo {
    font-size: 1.5rem;
    font-weight: 700;
    color: #667eea;
  }
  
  .nav-menu {
    display: flex;
    gap: 24px;
    margin-left: auto;
    
    @media (max-width: 768px) {
      display: none;
      position: absolute;
      top: 100%;
      left: 0;
      right: 0;
      flex-direction: column;
      background: white;
      padding: 16px;
      box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
      
      &.active {
        display: flex;
      }
    }
  }
  
  .nav-toggle {
    display: none;
    
    @media (max-width: 768px) {
      display: block;
      margin-left: auto;
    }
  }
}

/* 响应式网格布局 */
.grid {
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(4, 1fr);
  
  @media (max-width: 1024px) {
    grid-template-columns: repeat(3, 1fr);
  }
  
  @media (max-width: 768px) {
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
  }
  
  @media (max-width: 480px) {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  
  .grid-item {
    background: white;
    border-radius: 8px;
    padding: 20px;
    
    @media (max-width: 768px) {
      padding: 16px;
    }
    
    &:hover {
      transform: translateY(-4px);
      box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
    }
  }
}

高级技巧

1. 容器查询

容器查询是媒体查询的补充,让我们能够根据容器的大小而不是视口大小来调整样式:

/* 定义容器 */
.card-container {
  container-type: inline-size;
  container-name: card;
}

/* 容器查询 */
@container card (min-width: 400px) {
  .card {
    display: flex;
    gap: 20px;
    
    .card-image {
      flex: 0 0 150px;
    }
    
    .card-content {
      flex: 1;
    }
  }
}

@container card (max-width: 399px) {
  .card {
    .card-image {
      width: 100%;
      height: 200px;
    }
  }
}

2. 嵌套深度控制

避免过度嵌套,保持代码可读性:

/* 不好的做法 - 嵌套过深 */
.component {
  .header {
    .nav {
      .menu {
        .item {
          .link {
            /* 太深了! */
          }
        }
      }
    }
  }
}

/* 好的做法 - 最多3层嵌套 */
.component { }
.component-header { }
.component-nav { }
.component-menu-item { }

3. 混合使用策略

/* 组件基础样式 */
.button {
  padding: 12px 24px;
  border-radius: 6px;
  font-weight: 500;
  transition: all 0.2s ease;
  
  /* 变体 */
  &.primary {
    background: #667eea;
    color: white;
    
    &:hover {
      background: #5a6fd8;
    }
  }
  
  &.secondary {
    background: transparent;
    border: 2px solid #667eea;
    color: #667eea;
    
    &:hover {
      background: #667eea;
      color: white;
    }
  }
  
  /* 尺寸 */
  &.small {
    padding: 8px 16px;
    font-size: 0.875rem;
  }
  
  &.large {
    padding: 16px 32px;
    font-size: 1.125rem;
  }
  
  /* 响应式 */
  @media (max-width: 768px) {
    padding: 10px 20px;
    font-size: 0.875rem;
  }
}

浏览器兼容性

CSS 嵌套:

  • Chrome 112+
  • Firefox 117+
  • Safari 16.5+
  • Edge 112+

容器查询:

  • Chrome 105+
  • Firefox 110+
  • Safari 16+
  • Edge 105+

对于旧版浏览器,可以使用 PostCSS 等工具进行转换。

性能优化

1. 避免过度嵌套

/* 不好的做法 */
.a {
  .b {
    .c {
      .d {
        color: red;
      }
    }
  }
}

/* 好的做法 */
.a-b-c-d {
  color: red;
}

2. 媒体查询顺序

/* 移动优先 */
.component {
  /* 移动端样式 */
  padding: 16px;
  
  @media (min-width: 768px) {
    /* 平板 */
    padding: 24px;
  }
  
  @media (min-width: 1024px) {
    /* 桌面 */
    padding: 32px;
  }
}

写在最后

CSS 嵌套和媒体查询让样式组织更加优雅。它们让我们能够以更符合直觉的方式编写 CSS,提高代码的可读性和可维护性。

正如我常说的:「CSS 是流动的韵律,JS 是叙事的节奏。」嵌套和媒体查询让这种韵律更加清晰有序。记住,像素不能偏差 1px,结构要层次分明。

在实际项目中,合理使用这些特性可以:

  • 提高代码可读性
  • 简化响应式设计
  • 增强样式可维护性
  • 减少代码重复

希望这篇文章能帮助你更好地理解和使用 CSS 嵌套与媒体查询。如果你有任何问题或想法,欢迎在评论区分享!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐