CSS变量(Custom Properties)是主题切换的正确方案,HTML无原生变量;data-属性仅作标记,需配合CSS选择器或JS生效;:root与[data-theme]组合最稳妥;var()必须设回退值;localStorage恢复需在CSS解析前完成。

CSS 变量(Custom Properties)能完美支撑主题切换,HTML 本身没有“HTML 变量”这一概念——所有所谓“HTML 变量”实际是误称,真正起作用的是 CSS 中的 --* 自定义属性。
为什么不能用 HTML 属性当“变量”来切换主题
有人尝试用 data-theme 或 id 等 HTML 属性直接控制样式,但这些属性本身不带计算能力。它们只有配合 CSS 选择器(如 [data-theme="dark"])或 JavaScript 才能触发样式变化。单纯写 <div data-color="blue"> 不会让背景变蓝——没声明规则就等于没定义。
-
data-属性只是标记,不是变量,不能被var()引用 - 试图用
style="color: data-color"这类写法会直接报错,浏览器根本不识别 - 若强行用 JS 读取 HTML 属性再 setStyle,等于绕过 CSS 变量机制,失去批量响应、继承、级联等优势
:root 和 [data-theme] 是最稳妥的组合方式
主流可靠做法是:在 :root 定义默认值,在 [data-theme="dark"] 下覆盖同名变量。这样既保持语义清晰,又避免 class 冲突(比如多个 class 同时作用于 html 元素时优先级难控)。
- 把
data-theme放在<html>上,确保全局生效:<html data-theme="light"> - CSS 中用
[data-theme="dark"] { --bg-color: #121212; }覆盖,不用写html[data-theme="dark"] :root这种冗余写法 - JS 切换只需一行:
document.documentElement.setAttribute('data-theme', 'dark'),比classList.toggle更干净,无残留风险
回退值不是可选项,而是必须项
如果用户浏览器不支持 CSS 变量(如 IE11 或极老安卓 WebView),var(--color) 会直接失效,导致样式崩塌。必须为每个 var() 提供回退值:
立即学习“前端免费学习笔记(深入)”;
- 写法必须是:
color: var(--text-color, #333);,逗号后是纯色值或已定义变量 - 不能写成:
color: var(--text-color) #333;(语法错误)或var(--text-color, var(--fallback))(嵌套无效) - 回退值建议用设计系统里最保守的通用色,比如浅色模式用
#333,深色模式用#eee,而非透明或 inherit
localStorage 读写时机容易出错
页面加载时从 localStorage 恢复主题,必须在 CSS 解析完成前完成设置,否则会出现“闪白”或“闪黑”——即先按默认主题渲染,再跳变。
- 不要把主题恢复逻辑放在
window.onload或DOMContentLoaded之后,太晚 - 最佳位置是
<script>标签紧贴<html>开头,或使用document.write注入(慎用),更推荐内联脚本 +documentElement.setAttribute - 记得同步处理
prefers-color-scheme:若 localStorage 为空,才 fallback 到系统偏好,避免覆盖用户手动选择
真正复杂的地方在于变量粒度和继承链——比如 --border-color 是否该细分为 --border-color-input、--border-color-card?这决定了后期维护成本。多数项目卡在这里,而不是切换逻辑本身。



















