主题变量必须定义在 :root,通过 class 切换(如 .theme-dark)覆盖值,配合 var() 引用实现全局响应式;禁止硬编码、清空 cssText 或依赖 theme-color meta 标签动态更新。

必须把主题变量定义在 :root,别塞进 class 或组件内部
自定义组件(比如 Web Components、Vue 的 、React 封装的 ThemeProvider)能读到 CSS 变量,前提是这些变量挂载在文档顶层作用域。写成 .theme-dark { --primary: #1e40af; } 是无效的——浏览器会把它当两个独立选择器处理,--primary 根本不会进入级联链。
真正生效的写法只有这一种:
:root {
--theme-primary: #3b82f6;
--theme-bg: #ffffff;
}
.theme-dark {
--theme-primary: #60a5fa;
--theme-bg: #111827;
}
这样,只要给 切换 class,所有用 var(--theme-primary) 的地方(包括 Shadow DOM 内部)都会响应更新。Vue/React 组件里如果用了 style={{ color: `var(--theme-primary)` }},也得靠这个机制才能联动。
var() 必须显式出现在每个用色位置,漏一个就断链
只改 :root 里的值没用,关键在“引用”。哪怕整个页面 99% 都用了 var(--theme-primary),只要有一个 .card:hover { background-color: #2563eb; } 还是硬编码,悬停时颜色就永远卡死。
容易被忽略的引用点包括:
-
::before和::after里的background、color、border-color - 表单控件:
input:focus、select:disabled、textarea::placeholder - SVG 图标:内联
fill或stroke必须写成fill: var(--theme-primary); - Font Awesome 这类字体图标:需在对应 class 上补
color: var(--theme-primary);
JS 切换主题时,用 setProperty(),别碰 cssText
常见错误是这么写:
document.documentElement.style.cssText = '--theme-primary: #1e40af; --theme-bg: #111827;';
这会清空所有已有的内联样式,包括其他 JS 注入的动态样式或框架管理的 class,导致按钮禁用态、动画状态等意外失效。
正确做法是逐个设置:
document.documentElement.style.setProperty('--theme-primary', '#1e40af');
document.documentElement.style.setProperty('--theme-bg', '#111827');
另外注意:
- 为需要过渡的属性(如
background-color)提前加transition: background-color 0.2s;,否则重绘生硬 - 如果用 class 切换(如
html.dark),确保.dark :root规则权重足够,且放在默认:root定义之后 - 深色模式要用
@media (prefers-color-scheme: dark)直接重写:root,别嵌套在 class 里
别指望 theme-color meta 标签响应 CSS 变量
和 CSS 自定义属性完全隔离。它不参与样式计算,也不响应 JS 修改——你调用 document.querySelector('meta[name="theme-color"]').setAttribute('content', '#1e40af'),只对后续加载有效,当前页顶部栏不会变色,iOS 上基本无效。
真正可靠的做法是预设多套 meta 标签并用 media 控制显隐:
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"><meta name="theme-color" content="#121212" media="(prefers-color-scheme: dark)">
如果还要支持用户手动切换,就得配合 localStorage + 手动切换 class,并同步更新对应 meta 的 content 值——但仅限安卓 Chrome 有较大概率生效,iOS 仍建议放弃 runtime 更新,专注预设和系统偏好。
最易被忽略的一点:所有主题变量必须预先声明默认值,哪怕只是占位;否则在 JS 读取时可能返回 undefined,导致深色模式计算中断或 fallback 失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











