本文详解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原生嵌套!

评论(0)