局部覆盖必须在目标容器上直接声明变量,不能依赖:root或伪类;伪类声明变量仅影响自身伪元素,不继承给子元素;变量查找遵循dom祖先链就近原则,与选择器权重和源顺序无关。

局部覆盖必须在目标容器上直接声明,不能靠:root或伪类“劫持”
想让某个区域用深色背景但不影响全局?别写 :root 里套 .theme-dark,那根本无效——:root 只匹配 根元素,放在任何其他选择器里都只是废代码。真正起效的是把变量直接挂到容器元素上:.section-a { --bg-color: #1a1a1a; }。子元素读 var(--bg-color) 时,会沿 DOM 祖先链向上查找,取第一个有效声明,而不是看选择器名字是否带“dark”。
伪类(:hover、:focus等)本身不能声明变量,但可以配合容器生效
你不能写 button:hover { --color: red; } 然后指望按钮悬停时内部文字变红——变量声明在伪类里是合法语法,但它只对伪元素自身生效(比如 button:hover::before),不会影响 button 的子元素。常见错误是以为悬停时整个按钮区域的 var(--color) 会自动更新,其实不会。正确做法是:把变量声明在容器上,再用伪类触发样式变化:
button {
--text-color: #333;
}
button:hover {
--text-color: #d32f2f; /* 这行才真正覆盖变量 */
}
button span {
color: var(--text-color); /* 悬停时这里才会变红 */
}
容器选择器越具体,局部覆盖越可控,但也越容易被意外覆盖
变量覆盖不看 DOM 深度,只看 CSS 声明顺序 + 选择器权重。如果同时存在:
.card { --primary: blue; }button { --primary: red; }.card button { --primary: green; }
那么 .card button 内部所有 var(--primary) 都取 green,因为这条规则权重最高且声明在最后。但如果你漏写了 .card button,只写了 button,那它可能被更早加载的第三方库中高权重规则(如 .el-button)覆盖,导致局部失效。调试时打开 DevTools → Computed 面板 → 搜 --primary,点开小箭头就能看到值来自哪一行、被谁继承、有没有被划掉。
小程序和老浏览器里,局部覆盖得换思路
微信/支付宝小程序原生不支持 :root,也不能在 WXSS 里声明变量;IE 完全无视 var()。这时候“局部覆盖”不是加个类名就行,而是要靠 JS 动态注入 style 属性:
<view class="theme-section" style="--bg-color: #121212; --text-color: #e0e0e0;"><text class="title">标题</text></view>
然后在 WXSS 中写:.title { color: var(--text-color); }。注意两点:变量必须写在祖先元素的 style 属性里(不能写在 WXSS 文件中),且名称必须以 -- 开头。兼容性兜底也得手动加:color: #333; color: var(--text-color, #333);。
局部覆盖最易被忽略的一点:它不依赖“作用域块”,而依赖“声明位置”和“继承路径”。哪怕你把变量写在 .card 的最后一个 CSS 规则里,只要它没出现在目标元素的任意一个祖先上,var() 就读不到。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











