无需登录 数据私有 本地保存

暗黑模式切换演示 - 三种实现对比

13
0
0
0

暗黑模式切换方案对比

三种主流暗黑模式实现方案的可视化对比演示 —— CSS变量 · Class切换 · 系统偏好跟随

方案一 CSS 变量
CSS Custom Properties
浅色模式
📱 我的应用 在线

欢迎回来!

这是使用CSS变量控制主题的演示。

📋 任务列表

✅ 完成设计稿

⏳ 代码审查

切换预览:
:root {
  --bg: #fff;
  --text: #333;
}
[data-theme="dark"] {
  --bg: #1e1e2e;
  --text: #e0e0e0;
}
body {
  background: var(--bg);
  color: var(--text);
}
// JS切换:
document.documentElement
  .setAttribute('data-theme', 'dark');
灵活精细 易扩展 需CSS变量兼容
方案二 Class 切换
CSS Class Toggle
浅色模式

欢迎回来!

使用Class切换实现暗黑模式。

📋 任务列表

✅ 完成设计稿

⏳ 代码审查

切换预览:
/* 默认浅色样式 */
body { background:#fff; color:#333; }
.card { background:#f8f9fa; }

/* 暗黑模式覆盖 */
body.dark-mode { background:#1e1e2e; color:#e0e0e0; }
body.dark-mode .card { background:#2d2d3f; }

// JS切换:
document.body.classList.toggle('dark-mode');
localStorage.setItem('theme','dark');
简单直观 兼容性好 样式冗余
方案三 系统偏好
prefers-color-scheme
跟随系统

自动适配系统偏好

使用prefers-color-scheme媒体查询,自动跟随系统。

📋 任务列表

✅ 完成设计稿

⏳ 代码审查

模拟系统偏好: (模拟切换)
/* 自动跟随系统 */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1e1e2e;
    --text: #e0e0e0;
  }
}
// JS监听系统偏好变化:
const mq = window.matchMedia(
  '(prefers-color-scheme: dark)'
);
mq.addEventListener('change', (e) => {
  updateTheme(e.matches);
});
// 同时支持手动覆盖到localStorage
自动适配 用户友好 需手动覆盖逻辑
三种方案对比总结
对比维度 方案一CSS变量 方案二Class切换 方案三系统偏好
实现复杂度 ⭐⭐ 中等 ⭐ 简单 ⭐⭐⭐ 较复杂
样式维护 ✅ 集中管理变量 ⚠️ 样式分散 ✅ 可结合变量
扩展性 ✅ 多主题易扩展 ⚠️ 多主题需大量覆盖 ✅ 仅双主题
浏览器兼容 ⚠️ IE不兼容 ✅ 全兼容 ⚠️ IE不兼容
用户偏好存储 ✅ localStorage ✅ localStorage ✅ 自动+手动覆盖
初始加载闪烁 需处理 需处理 ✅ 无闪烁
适用场景 中大型项目、多主题 小型项目、快速实现 注重用户体验的项目
避免闪烁 (FOUC)

在<head>中内联一小段JS,读取localStorage并在页面渲染前设置属性,防止主题切换时的闪烁。

持久化偏好

使用localStorage存储用户选择,结合系统偏好作为默认值,提供最佳体验。

语义化颜色

使用语义化CSS变量名(如--surface、--on-surface),而非直接使用颜色名,便于主题扩展。

混合方案

实际项目可结合三种方案:CSS变量定义颜色 + Class控制切换 + 系统偏好作为默认值。

常见问题与知识点
什么是 FOUC(Flash of Unstyled Content)?暗黑模式如何避免?

FOUC是指在页面加载时短暂出现错误主题的闪烁。避免方法:在<head>中放置内联脚本,在DOM渲染前读取localStorage中的主题偏好,并立即设置<html>的data-theme属性或body的class。这样浏览器在首次绘制时就已经应用了正确的主题。

三种方案可以混合使用吗?最佳实践是什么?

完全可以,且推荐混合使用。推荐架构:使用CSS变量定义所有颜色(方案一),通过body上的class来控制主题切换(方案二),默认值使用prefers-color-scheme媒体查询(方案三),并用localStorage存储用户的手动选择。这样兼顾了灵活性、兼容性和用户体验。

如何检测用户系统是否开启了暗黑模式?

使用window.matchMedia('(prefers-color-scheme: dark)')。返回的MediaQueryList对象有.matches属性(布尔值),并且可以通过addEventListener('change', callback)监听系统偏好的实时变化。这在macOS、iOS、Android等系统上都有效。

CSS变量方案在IE浏览器上不兼容怎么办?

如果必须支持IE,可以:1) 使用方案二(Class切换)作为降级方案;2) 使用PostCSS插件自动生成带fallback的样式;3) 使用CSS变量polyfill。不过随着IE在2022年正式退役,大多数现代项目已不再需要兼容IE。

暗黑模式下的图片和图标如何处理?

图片可以使用CSS的filter: brightness(0.9)降低亮度;SVG图标使用currentColor继承文字颜色;对于重要图片,可以使用<picture>元素配合prefers-color-scheme媒体查询提供不同版本的图片资源。

暗黑模式下的阴影效果应该如何调整?

在暗色背景下,传统的灰色阴影几乎不可见。推荐使用更暗的阴影颜色(如rgba(0,0,0,0.4))或使用发光效果(如box-shadow使用较亮的边框色)来替代。也可以使用微妙的边框来分隔元素,替代阴影的层次感作用。

如何在服务端渲染(SSR)中处理暗黑模式?

SSR场景下,可以通过读取请求中的Cookie(存储主题偏好)或解析Sec-CH-Prefers-Color-Scheme客户端提示头来在服务端判断用户偏好,直接在HTML中设置正确的初始主题属性。对于不支持客户端提示的浏览器,可使用Cookie作为fallback,并在客户端hydration后同步。

推荐使用 CSS变量 + Class切换 + 系统偏好 的混合方案,兼顾灵活性与兼容性

关键词:暗黑模式 · Dark Mode · CSS变量 · prefers-color-scheme · 主题切换 · 前端开发