CSS2024-01-14
返回首页

原生 CSS 嵌套语法实战

原生 CSS 嵌套语法实战

CSS 原生嵌套终于在 2023 年底得到主流浏览器支持。不用预处理器也能写嵌套了。

基本语法

/* 原生嵌套 */
.card {
  padding: 1rem;
  
  & .title {
    font-size: 1.5rem;
  }
  
  & .content {
    color: #666;
  }
  
  &:hover {
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  }
}

编译后:

.card {
  padding: 1rem;
}

.card .title {
  font-size: 1.5rem;
}

.card .content {
  color: #666;
}

.card:hover {
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

嵌套选择器

& 代表父选择器,可以拼接在任何位置:

.button {
  background: blue;
  
  &:hover {
    background: darkblue;
  }
  
  &:active {
    transform: scale(0.98);
  }
  
  &:disabled {
    opacity: 0.5;
  }
}

也可以用在选择器中间:

.container {
  body.dark & {
    background: #1a1a1a;
  }
  
  .sidebar & {
    width: 100%;
  }
}

嵌套 @ 规则

媒体查询可以嵌套在规则内部:

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  
  @media (max-width: 768px) {
    grid-template-columns: repeat(2, 1fr);
  }
  
  @media (max-width: 480px) {
    grid-template-columns: 1fr;
  }
}

这比传统的写法清晰很多:

/* 传统写法 */
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

@media (max-width: 768px) {
  .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 480px) {
  .grid {
    grid-template-columns: 1fr;
  }
}

实际组件示例

/* 一个完整的卡片组件 */
.post-card {
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
  transition: transform 0.2s, box-shadow 0.2s;
  
  & .thumbnail {
    aspect-ratio: 16 / 9;
    object-fit: cover;
    width: 100%;
  }
  
  & .body {
    padding: 1rem;
    
    & .title {
      font-size: 1.25rem;
      font-weight: 600;
      margin-bottom: 0.5rem;
      
      &:hover {
        color: #0070f3;
      }
    }
    
    & .excerpt {
      color: #666;
      line-height: 1.6;
    }
  }
  
  & .footer {
    padding: 0.75rem 1rem;
    border-top: 1px solid #eee;
    display: flex;
    justify-content: space-between;
    align-items: center;
    
    & .date {
      font-size: 0.875rem;
      color: #999;
    }
    
    & .tag {
      font-size: 0.75rem;
      padding: 0.25rem 0.5rem;
      background: #f0f0f0;
      border-radius: 4px;
    }
  }
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  }
  
  @media (prefers-color-scheme: dark) {
    background: #1a1a1a;
    
    & .body .excerpt {
      color: #aaa;
    }
    
    & .footer {
      border-top-color: #333;
    }
  }
}

与预处理器对比

原生嵌套和 Sass/Less 的区别:

特性 原生 CSS Sass
嵌套选择器
嵌套属性
变量 ✅ (--var) ✅ ($var)
混合宏
函数
继承

原生嵌套能满足大部分场景,但复杂项目还是需要预处理器或 PostCSS。

浏览器支持

2024 年初,所有主流浏览器都已支持:

  • Chrome 120+
  • Firefox 121+
  • Safari 17.2+
  • Edge 120+

如果需要兼容旧浏览器,可以用 PostCSS 的 postcss-nesting 插件:

npm install postcss-nesting
// postcss.config.js
module.exports = {
  plugins: {
    'postcss-nesting': true,
  }
};

小结

原生 CSS 嵌套让样式代码更简洁、更易维护。对于不需要复杂预处理器功能的项目,可以直接使用原生语法,减少构建依赖。