游乐游手机版
首页/前端开发/文章详情

CSS实现深色模式切换的方法与实战技巧

时间:2026-08-18 16:22
实现 CSS 深色模式切换时,变量必须声明在 :root 中,因为它是唯一能够稳定保证全局继承的根节点;如果把变量写在 dark、body 或组件类里,input 等同级节点以及部分原生表单控件可能无法正确读取变量,Shadow DOM 内部同样不会自动继承,通常需要额外手动传递。CSS 深色模式

实现 CSS 深色模式切换时,变量必须声明在 :root 中,因为它是唯一能够稳定保证全局继承的根节点;如果把变量写在 .dark、body 或组件类里,input 等同级节点以及部分原生表单控件可能无法正确读取变量,Shadow DOM 内部同样不会自动继承,通常需要额外手动传递。

如何用CSS实现深色模式切换?

CSS 深色模式切换必须使用 :root 声明变量,并结合 @media (prefers-color-scheme: dark).dark 类形成三层联动,三者缺一不可。

为什么所有变量必须写在 :root 里?

CSS 自定义属性依赖继承机制向下传递,而只有 :root(也就是 元素)才能最大程度确保任意节点通过 var(--bg-color) 获取到正确的变量值。若变量写在 .darkbody 或某个组件类中,那么这些变量只会对当前选择器及其后代元素生效。

  • .dark { --bg-color: #121212; } → 如果 没有被包裹在 .dark 内,就可能 fallback 到透明色或浏览器默认背景色
  • body { --text-color: #eee; } → 当 var(--text-color) 层级参与计算时,根本无法找到对应定义
  • Shadow DOM 内部不会自动继承外部 :root 变量,需要在 :host::slotted 中手动传入

@media (prefers-color-scheme: dark) 怎么写才不白写?

它的作用只是作为“系统深色模式偏好”的兜底方案,并不是万能的主题切换开关。若声明位置错误,或者变量未提前定义完整,页面刷新后样式就可能失效。

  • 必须写在 :root 默认变量声明之后,否则部分旧版 Safari 可能会直接忽略
  • 所有变量都要先在 :root 中完整定义默认值,否则当系统为 no-preference 时,var(--border-color) 可能 fallback 为 transparent
  • 不要只覆盖一部分变量:如果漏掉 --shadow-sm,那么使用了 box-shadow: var(--shadow-sm) 的按钮就会失去阴影效果
  • 不要嵌套错误写法:@media (max-width: 768px) { @media (prefers-color-scheme: dark) { } } 属于无效结构

用户点按钮切换时,JS 该做什么、不该做什么?

核心原则是只切换 class,不要直接操作 style.setProperty()。后者会破坏整套基于媒体查询和变量继承的逻辑,同时也会让后续维护成本迅速上升。

  • ✅ 推荐做法:document.documentElement.classList.toggle('dark')
  • ❌ 应避免:document.documentElement.style.setProperty('--bg-color', '#121212')
  • 初始化执行必须早于首屏渲染:应直接放在