全局变量必须定义在:root,不能写在页面级选择器里;语义化变量如--primary-color需声明在:root以确保跨页面复用;页面专属颜色应通过唯一ID容器覆盖;主题切换应使用html[data-theme]而非@media;变量名需严格区分大小写且避免拼写错误。

全局变量必须定义在 :root,不能写在页面级选择器里
跨页面复用颜色的前提是:所有页面都能读到同一组基础值。这意味着--primary-color、--text-color-dark这类语义化变量,必须声明在:root伪类下——它是整个文档的根作用域,所有元素默认继承。
常见错误是把变量塞进body或.page-home里,结果其他页面压根取不到。比如你在body#page-about里写了--primary-color: #2c3e50,那header在首页就拿不到这个值,除非它也在那个body内部。
-
:root是唯一能保证“所有页面都可见”的位置 - 变量名要带语义前缀(如
--brand-primary),避免和第三方库冲突 - 不要在
@media块里重复定义同一变量,容易因加载顺序导致覆盖失效 - 回退值(如
var(--primary-color, #007bff))必须是静态色值,不能嵌套var()
页面专属颜色要用 ID 容器覆盖,而不是改 :root
如果首页页眉要蓝、联系页要红,不能去动:root里的--header-bg——那样所有页面都会变。正确做法是让每个body带唯一 ID,再在该 ID 选择器上重定义变量:
body#page-home { --header-bg: #3498db; }
body#page-contact { --header-bg: #e74c3c; }
header { background-color: var(--header-bg, #f8f9fa); }
关键点在于:header必须是body#page-contact的后代元素,否则取不到--header-bg;也不能把变量直接写在header自己身上,否则子元素用不到。
立即学习“前端免费学习笔记(深入)”;
- ID 必须唯一且稳定,不能靠 JS 动态生成后又不更新 CSS 作用域
- 变量覆盖只对当前 ID 及其后代生效,不影响其他页面
- 若页眉是固定定位或脱离 normal flow,需确认它仍在对应
bodyDOM 树内
主题切换必须靠 HTML class 或 data 属性,别依赖 @media 重定义
深色模式、用户偏好切换这类需求,不能靠@media (prefers-color-scheme: dark)直接重写:root变量——有些浏览器(尤其是 Safari 旧版)会忽略媒体查询中的变量变更,或者优先级错乱。
更可靠的方式是把主题挂到html元素上:
html[data-theme="dark"] {
--bg-color: #1e1e1e;
--text-color: #e0e0e0;
}
html[data-theme="light"] {
--bg-color: #ffffff;
--text-color: #343a40;
}
然后用 JS 切换document.documentElement.setAttribute('data-theme', 'dark'),CSS 自动响应。
- 避免在
:root里同时写浅色和深色规则,容易被覆盖 - JS 修改变量时,优先用
document.documentElement.style.setProperty(),而非操作 class - SSR 渲染时,服务端需同步输出正确的
data-theme属性,否则首屏闪动
变量名冲突和拼写错误是最难排查的问题
你改了--primary-color,但按钮没变色?大概率是变量名拼错了,比如--primar-color或--primary-colour。浏览器不会报错,只会静默回退到 fallback 值或默认值。
另一个常见陷阱是混用 CSS 变量和预处理器变量:Sass 的$primary编译完就没了,JS 读不到,也无法被var()引用。两者不能互相转换,命名空间也完全隔离。
- 用 DevTools 的 Computed 面板检查元素实际计算出的值,别只看 Styles 面板里的声明
- 变量名区分大小写:
--HeaderBg和--header-bg是两个变量 - 内联样式(
style="--color: red")优先级高于 CSS 文件中的:root定义,调试时注意覆盖链


















