本文详解2026年CSS原生嵌套语法,替代Sass/Less预处理器。

什么是CSS嵌套(CSS Nesting)

CSS嵌套(2023年Chrome 112+支持):

  • 原生CSS支持嵌套(无需Sass/Less)
  • 减少代码量(减少重复选择器)
  • 提升可维护性

vs Sass嵌套:

  • Sass嵌套:需要编译(.scss → .css)
  • CSS原生嵌套:浏览器直接支持(无需编译)

浏览器支持(2026年)

支持情况:

  • Chrome 112+ ✅(2023年3月)
  • Firefox 115+ ✅(2023年7月)
  • Safari 16.5+ ✅(2023年5月)
  • Edge 112+ ✅(2023年4月)

全球支持率:95%(2026年)

不支持:IE11(已淘汰)

实战一:基础嵌套语法

传统CSS(无嵌套)

/* 传统写法:重复选择器 */

.header { padding: 20px; }

.header .logo { width: 100px; }

.header .nav { display: flex; }

.header .nav a { color: #333; }

.header .nav a:hover { color: #007bff; }

CSS原生嵌套

/* 原生嵌套:简洁 */

.header {

padding: 20px;

.logo {

width: 100px;

}

.nav {

display: flex;

a {

color: #333;

&:hover {

color: #007bff;

}

}

}

}

使用`&`符号(父选择器引用)

/* & 代表父选择器 */

.button {

background: #007bff;

color: white;

/* & = .button */

&:hover {

background: #0056b3;

}

/* & = .button */

&.primary {

background: #28a745;

}

/* & = .button */

.icon + & {

margin-left: 8px;

}

}

实战二:媒体查询嵌套(@media)

传统媒体查询(无嵌套)

/* 传统写法:重复选择器 */

.container { max-width: 1200px; }

@media (max-width: 768px) {

.container { max-width: 100%; }

}

@media (max-width: 480px) {

.container { padding: 10px; }

}

嵌套媒体查询

/* 嵌套写法:简洁 */

.container {

max-width: 1200px;

@media (max-width: 768px) {

max-width: 100%;

}

@media (max-width: 480px) {

padding: 10px;

}

}

复杂媒体查询

.hero {

height: 500px;

background: url('hero-desktop.jpg');

@media (max-width: 768px) {

height: 300px;

background: url('hero-mobile.jpg');

}

@media (max-width: 768px) and (orientation: landscape) {

height: 200px;

}

@media (prefers-color-scheme: dark) {

background: #333;

color: white;

}

}

实战三:组合选择器嵌套

兄弟选择器(`+` / `~`)

/* 相邻兄弟选择器 */

.list {

li {

padding: 10px;

/* 下一个li */

+ li {

border-top: 1px solid #ddd;

}

}

}

/* 通用兄弟选择器 */

.form {

input {

margin-bottom: 10px;

/* 所有后面的p */

~ p {

color: #666;

}

}

}

子选择器(`>`)

.nav {

ul {

list-style: none;

> li {

display: inline-block;

> a {

padding: 8px 16px;

}

}

}

}

实战四:伪类与伪元素嵌套

伪类(:hover, :focus, :nth-child)

.table {

tr {

&:nth-child(even) {

background: #f8f9fa;

}

&:hover {

background: #e9ecef;

}

}

td {

padding: 12px;

&:first-child {

font-weight: bold;

}

}

}

伪元素(::before, ::after)

.tooltip {

position: relative;

&::before {

content: attr(data-tip);

position: absolute;

bottom: 100%;

left: 50%;

transform: translateX(-50%);

background: #333;

color: white;

padding: 4px 8px;

border-radius: 4px;

opacity: 0;

transition: opacity 0.3s;

}

&:hover::before {

opacity: 1;

}

}

实战五:CSS层叠层(@layer)

什么是@layer

/* 定义层叠层(控制优先级) */

@layer reset, base, components, utilities;

/* 按顺序排列 */

@layer reset {

* { margin: 0; padding: 0; }

}

@layer base {

body { font-family: sans-serif; }

}

@layer components {

.button { ... }

}

@layer utilities {

.text-center { text-align: center; }

}

嵌套 + @layer

@layer components {

.card {

padding: 20px;

border: 1px solid #ddd;

.title {

font-size: 24px;

@media (max-width: 768px) {

font-size: 20px;

}

}

.button {

background: #007bff;

&:hover {

background: #0056b3;

}

}

}

}

实战六::has()选择器(父选择器)

什么是:has()

/* :has() - 选择包含特定子元素的父元素 */

/* 选择包含img的.card */

.card:has(img) {

padding-top: 0;

}

/* 选择后面跟着p的h2 */

h2:has(+ p) {

margin-bottom: 8px;

}

/* 选择不包含img的.card */

.card:not(:has(img)) {

padding: 20px;

}

实战:根据子元素调整样式

/* 如果.form包含.required,则改变边框 */

.form:has(.required) {

border: 2px solid #dc3545;

}

/* 如果.card包含.video,则改变宽高 */

.card:has(.video) {

aspect-ratio: 16/9;

}

/* 如果.nav包含5个以上li,则改变布局 */

.nav:has(li:nth-child(5)) {

flex-wrap: wrap;

}

实战七:容器查询(@container)

什么是容器查询

/* 传统:媒体查询(基于视口) */

@media (max-width: 768px) {

.card { flex-direction: column; }

}

/* 新:容器查询(基于容器大小) */

.card-container {

container-type: inline-size;

container-name: card;

}

.card {

/* 如果容器宽度 < 600px */

@container card (max-width: 600px) {

flex-direction: column;

}

}

实战:响应式卡片

/* 定义容器 */

.articles {

container-type: inline-size;

container-name: articles;

}

/* 卡片默认样式(大容器) */

.card {

display: grid;

grid-template-columns: 200px 1fr;

gap: 20px;

/* 如果容器宽度 < 600px */

@container articles (max-width: 600px) {

grid-template-columns: 1fr;

}

}

.card img {

width: 100%;

/* 如果容器宽度 < 600px */

@container articles (max-width: 600px) {

aspect-ratio: 16/9;

object-fit: cover;

}

}

实战八:CSS变量作用域(Custom Properties)

嵌套 + CSS变量

:root {

--primary-color: #007bff;

--secondary-color: #6c757d;

}

.button {

/* 局部变量(覆盖全局) */

--primary-color: #28a745;

background: var(--primary-color);

color: white;

&:hover {

/* 使用calc计算 */

background: color-mix(in srgb, var(--primary-color) 80%, black);

}

&.outline {

background: transparent;

border: 1px solid var(--primary-color);

color: var(--primary-color);

}

}

性能优化

优化一:避免过度嵌套(Deep Nesting)

/* ❌ 错误:嵌套过深(> 3层) */

.header {

.nav {

ul {

li {

a {

/* 太深了! */

color: #333;

}

}

}

}

}

/* ✅ 正确:扁平化 */

.header .nav a {

color: #333;

}

/* 或者限制嵌套深度 */

.header {

.nav a {

color: #333;

}

}

优化二:使用@layer管理优先级

/* 定义层叠顺序(从低到高) */

@layer reset, base, components, utilities;

@layer utilities {

/* 工具类优先级最高 */

.text-center { text-align: center !important; }

.mt-4 { margin-top: 1rem !important; }

}

决策建议

| 场景 | 是否使用CSS原生嵌套 | 理由 |

|------|-------------------|------|

| 新项目(2026年) | ✅ 强烈推荐 | 无需Sass,浏览器原生支持 |

| 旧项目(已用Sass) | ⚠️ 逐步迁移 | 可以混合使用 |

| 需要支持旧浏览器 | ❌ 不推荐 | 使用Sass编译 |

| 团队不熟悉CSS嵌套 | ⚠️ 培训后使用 | 学习曲线低 |

总结

CSS原生嵌套是2026年最重要的CSS新特性。替代Sass/Less,减少构建步骤,提升开发体验。

立即行动:在你的下一个项目中尝试CSS原生嵌套!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。