css变量不受css modules隔离,仍按原生级联逻辑生效,:root或祖先声明即全局可见,组件间变量天然互通,作用域与类名哈希无关。

CSS变量不被CSS Modules隔离
CSS Modules只重命名类名,--primary-color这类自定义属性完全不受影响——它仍走原生级联逻辑,在:root或任意祖先元素上声明就会全局生效。你写Button.module.css里定义:root { --bg: #fff; },Modal组件照样能读到、也能覆盖它。
变量作用域和类名作用域是两套系统
CSS Modules解决的是.button类名冲突,但var(--button-height)查的是CSS继承链,不是文件模块边界。哪怕两个组件都用import styles from './X.module.css',只要它们的DOM在同一个渲染树里,变量就天然互通。
- 变量查找路径:从当前元素向上逐层找最近定义了该变量的祖先,和JS作用域无关
- 类名哈希(如
Button_button_abc123)对--开头的变量名零影响 -
:global()在CSS Modules里只能包裹选择器,不能“包裹”变量声明
常见错误写法与替代方案
很多人试图在.module.css里写.my-button { --size: 16px; },指望它局部生效——但--size依然会从.my-button元素开始向上传播,子元素span调用var(--size)时取到的就是这个值,而父级若也设了同名变量,就立刻被覆盖。
- 真正有效的做法:给每个组件容器加唯一类名前缀,如
.ui-button,然后把变量声明绑死在这个选择器下:.ui-button { --button-padding: 8px; } - 避免在
:root塞项目级变量,尤其不要让第三方库和你自己都往:root写--color-primary - 动态主题场景下,用
data-theme配合选择器层级控制范围,比如[data-theme="dark"] .ui-button { --button-bg: #333; }
为什么@use或CSS-in-JS能绕过这个问题
SCSS的@use能让$color-primary变量私有化,因为它发生在编译期;CSS-in-JS(如Emotion)把变量转成内联style或带哈希的CSS Custom Property,本质是用JS作用域兜底。但纯CSS Modules + --var组合,没有任何构建时干预手段——变量就是浏览器原生机制,打包工具插不上手。
最容易被忽略的点:你以为开了CSS Modules就万事大吉,结果--开头的变量还在后台悄悄串场,直到某个Modal弹出来,按钮圆角突然变成8px才反应过来。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











