原生CSS嵌套中不能在嵌套块内定义真正局部的变量,但可在组件根选择器(如.card)中声明--card-bg等带前缀的CSS变量,后代通过var()继承使用,作用域限于该选择器及其后代。

现代CSS嵌套语法里怎么写局部变量
原生CSS嵌套(@nest 或标准嵌套语法)本身不支持在嵌套块内「定义」变量,但可以「使用」继承来的局部变量。真正能同时用嵌套 + 局部变量的场景,只存在于预处理器(如SCSS/Less)或已启用原生嵌套+CSS变量组合的现代浏览器中。
关键点在于:局部变量必须定义在嵌套选择器内部,且作用域仅限于该选择器及其后代;而嵌套结构只是让这个作用域更直观、更贴近DOM层级。
-
:root里定义的是全局变量,任何地方都能读,但改了就全页面响应——不适合模块隔离 - 想让
.card模块有自己的--bg、--shadow,就得在.card { --bg: white; }里定义 - 嵌套写法能让变量定义和使用紧挨着,比如
.card { --bg: #fff; &__header { background: var(--bg); } }
SCSS中嵌套+局部变量的实际写法
SCSS不是“原生CSS”,但它把嵌套和变量结合得最自然,也最常用。它的局部变量默认就是块级作用域,不需要额外修饰。
注意:SCSS变量用 $ 开头,和CSS变量(-- 开头)不是一回事;前者编译时替换,后者运行时可变。两者可以共存,但别混用。
立即学习“前端免费学习笔记(深入)”;
- 用
$变量做编译期配置:$card-padding: 16px; .card { padding: $card-padding; } - 用
--变量做运行时主题控制:.card { --card-bg: #fff; background: var(--card-bg); } - 嵌套中直接用
&引用父选择器,配合局部--变量,能清晰表达「这个模块的样式只影响自己」的意图
示例:
.card {
--card-bg: #ffffff;
--card-border: #e0e0e0;
background: var(--card-bg);
border: 1px solid var(--card-border);
&__title {
color: #333;
margin-bottom: var(--card-spacing, 12px);
}
&__content {
padding: 16px;
}
}
为什么不能在原生CSS嵌套里随便定义局部变量
目前(2026年)Chrome 120+、Safari 17.4+、Firefox 125+ 支持原生嵌套语法(.parent { .child { ... } }),但它只是语法糖,不改变CSS变量的作用域规则。
你写 .card { --bg: white; .card__header { background: var(--bg); } } 是合法的,但这个 --bg 并不是“只属于这个嵌套块”的变量——它只是恰好定义在 .card 规则里,依然遵循CSS变量的继承规则:所有 .card 的后代都能读到它。
- 没有真正的“块级作用域”封装,
--bg仍可能被子元素意外覆盖或读取 - 如果多个
.card实例需要不同背景色,还得靠JS动态设style="--bg: red",没法纯CSS隔离 - 所以「模块化」在这里更多靠命名约束(如BEM)+ 变量命名前缀(
--card-bg)来模拟,而非语言级隔离
嵌套+局部变量容易踩的三个坑
很多人以为写了嵌套就自动模块化了,其实只是视觉上整洁,逻辑上未必安全。
- 误把
$变量当--变量用:SCSS编译后变量就没了,无法用JS改;想动态换肤必须用--开头 - 嵌套过深导致选择器权重失控:比如
.card .card__header .card__title span,后期覆盖成本高 - 局部变量名没加模块前缀,造成冲突:
--bg太泛,应统一为--card-bg或--button-bg
真正可靠的模块化,是嵌套结构 + 前缀化CSS变量 + 明确的作用域定义位置(要么在组件根选择器,要么用 :where() 降权),三者缺一不可。


















