html无原生变量,主题切换依赖css变量(--*)与js配合;data-theme仅为开关属性,需css规则或js读取后触发样式变更,且必须预定义对应变量值。

HTML 本身没有“变量”概念,所谓“HTML变量”不能直接参与主题切换——所有生效的动态样式控制,最终都落在 CSS 变量(--*)和 JavaScript 的配合上。
为什么 data-theme 不是变量,只是开关
data-theme 是一个 HTML 属性,它本身不携带样式值,也不参与计算。它的作用仅仅是被 CSS 选择器(如 [data-theme="dark"])或 JS(如 document.documentElement.dataset.theme)读取,进而触发对应逻辑。
- 如果你只写
但没在 CSS 里写[data-theme="dark"] { --bg-color: #121212; },页面不会变暗 - JS 修改
dataset.theme后,样式不会自动更新——必须靠 CSS 规则已预先定义好该属性下的变量覆盖 - 多个
data-*属性并存时(比如data-theme和data-locale),它们彼此不干扰,也不能互相引用
:root 里的 --* 才是真变量,但必须设回退值
CSS 变量必须声明在 :root 或某个选择器作用域内,且调用时 var(--color, #000) 的第二个参数(回退值)不是可选项——它是防止 FOUC 或解析失败时样式崩塌的关键。
- 没设回退值时,
var(--missing)在浏览器中计算为invalid,导致该属性整条声明被忽略(例如color: var(--text-color);失效后会继承父级颜色) -
:root下声明的变量默认全局可用,但若你在.theme-dark :root里重定义,需确保该规则优先级 ≥ 默认:root,否则覆盖不生效 - 不要在内联
style里写style="color: var(--text-color)"——这无法被外部 CSS 变量接管,属于硬编码,会阻断主题逻辑
localStorage 恢复必须在 DOM 解析前完成
用户选了深色模式,刷新后闪一下白屏再变黑?大概率是主题恢复逻辑放太晚了。
-
DOMContentLoaded或window.onload触发时,CSS 已经解析并渲染过至少一次,默认主题早已画完——这时候再切主题,必然闪屏 - 正确做法:把脚本放在
开头紧贴标签后,用内联<script></script>立即读取localStorage.getItem('theme'),然后立刻调用document.documentElement.setAttribute('data-theme', ...) - 如果用 class 切换(如
theme-dark),也要同步清理其他可能残留的 class,避免class="theme-dark theme-light"这种冲突状态
getComputedStyle 读不到计算后的 var() 值
调试时别依赖 getComputedStyle(el).getPropertyValue('--primary-color') 判断主题是否生效——它返回的是原始字符串,不是最终渲染值。
- 如果变量值是
var(--fallback),这里就真返回字符串"var(--fallback)",不是颜色 - 想确认实际生效的颜色,应该查具体属性:
getComputedStyle(el).color、getComputedStyle(el).backgroundColor - 需要 JS 动态生成衍生色(比如深色模式下把主色变暗 20%),建议把基础色存在 JS 常量里,CSS 只消费,而不是让 JS 去解析 CSS 变量再计算
最易被忽略的一点:系统偏好(prefers-color-scheme)和用户手动选择必须分层处理。手动切换应始终优先于系统设置,否则用户点一下“切回亮色”,转头又被系统深色模式覆盖掉——这种体验断裂,往往源于没在初始化时检查 localStorage 是否存在有效值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











