暗黑模式切换必须用CSS变量+class控制,定义:root变量并切换html/body的dark类,统一所有颜色属性为var(),用localStorage记忆偏好,初始化时读取并同步按钮aria-pressed状态。

暗黑模式切换必须用 CSS 变量 + class 控制,别硬切 style
直接操作 document.body.style.backgroundColor 看似简单,但会覆盖内联样式、破坏 CSS 优先级、无法批量控制组件色值。真正可维护的做法是:定义一套 :root CSS 变量(比如 --bg-color、--text-color),再通过给 <html> 或 <body> 切换 class(如 dark)来触发变量重载。
常见错误是只改背景和文字色,结果按钮边框、输入框焦点、SVG 图标全乱套——所有颜色相关属性都得统一走变量,否则切换后视觉不一致。
-
:root里定义亮色模式默认值,.dark下重写同一组变量 - 所有用到颜色的地方写成
color: var(--text-color),而不是color: #333 - 不要给
.dark加!important,靠选择器权重或变量覆盖更干净
用 localStorage 记住用户偏好,避免每次刷新变回白天
浏览器刷新后 class 丢失是新手最常踩的坑。必须在页面加载时读取 localStorage.getItem('theme'),再决定是否加 dark 类;点击切换时同步写入 localStorage.setItem('theme', 'dark') 或 'light'。
注意:不能只依赖 window.matchMedia('(prefers-color-scheme: dark)') 自动适配系统设置,因为用户手动点过切换后,应以他的选择为准,系统设置只能当 fallback。
立即学习“前端免费学习笔记(深入)”;
- 初始化逻辑要放在
<script>标签里,且确保 DOM 加载完成后再执行(可用document.addEventListener('DOMContentLoaded', ...)) - 读取
localStorage时要判空:if (savedTheme === 'dark') { ... },别直接用==比较 - 切换按钮的
aria-pressed属性也要同步更新,方便屏幕阅读器识别状态
HTML 结构只需一个按钮 + 一行 script,别堆 JS 框架
零基础不用 React/Vue,纯 HTML + CSS + 原生 JS 就够了。核心就是:一个带 id="theme-toggle" 的按钮,一段不到 20 行的脚本,外加对应的 CSS 变量定义。
示例按钮写法:<button id="theme-toggle" aria-label="切换深色模式">?</button>;脚本里监听它的 click,然后切换 class 和 localStorage 即可。
- 按钮文案建议用图标(?/☀️)+
aria-label,比纯文字更直观且无障碍友好 - script 标签放
</body>前,避免 DOM 元素未就绪导致getElementById返回 null - 不需要引入任何外部库,
localStorage和classList.toggle()是所有现代浏览器原生支持的
兼容性检查重点看 Safari 13.1 和 Firefox 68+
CSS 变量在 IE 完全不支持,但 Safari 13.1+、Firefox 68+、Chrome 49+ 都没问题。如果你的目标用户基本不用 IE,就放心用;如果真要兼容 IE,就得改用 CSS class 全量覆盖(比如 .dark .card { background: #1e1e1e; }),但维护成本翻倍。
另一个容易忽略的是:Safari 对 prefers-color-scheme 的支持从 13.1 开始,旧版 Safari 不会触发媒体查询,但你的手动切换逻辑不受影响——只要 localStorage 和 class 切换正常,体验就不中断。
- 测试时打开 Safari 开发者工具 → “开发”菜单 → “进入响应式设计模式” → 切换“外观”模拟深色模式
- Firefox 需手动在
about:config设置ui.systemUsesDarkTheme = 1才能生效,别误判为不支持 - 移动端 iOS 13+/Android 10+ 系统级深色开关能自动触发
prefers-color-scheme,但用户手动切换仍优先
background: var(--bg-color),但父容器没继承该变量,就会回退到初始值(通常是 transparent 或 black)。务必在 :root 定义所有变量,并确认所有用到它们的选择器都能正确继承。



















