Pressidian
花园入口
笔记
项目
关于
实验室
GitHub
花园入口
笔记
项目
关于
实验室
GitHub

KNOWLEDGE PATHS

笔记库
当前位置
笔记库/前端/项目笔记/代达罗斯/考试

深色模式

2 分钟阅读 · Note

目录树 578 篇

            • 代达罗斯前端考试索引
            • 前端能力画像
            • 深色模式
            • 阅卷报告:CrateDetailPageContent
            • 阅卷报告:ThemeProvider.tsx(第二次)
            • CrateDialog
          • 项目待做
          • 性能优化
          • UI设计
      • 前端技术栈
    • 笔记目录
    • CLAUDE.md
    • Vue 组件与 Render 函数

关联笔记 6

↗代达罗斯前端考试索引反向链接↗阅卷报告:CrateDetailPageContent同一路径↗阅卷报告:ThemeProvider.tsx(第二次)同一路径↗CrateDialog同一路径↗前端能力画像同一路径↗EXAM-20260730-02 答辩与现场接管记录共同主题

核心就是靠 <html> 上的 dark class 来驱动全局主题切换。机制分三层,都在 apps/app/src/styles.css 里:

  1. Tailwind 的 dark 变体绑定到 .dark 类

styles.css:3

@custom-variant dark (&:is(.dark *));

这行告诉 Tailwind:所有带 dark: 前缀的类(如 dark:bg-card、dark:text-foreground)只有在某个祖先元素带有 .dark 类时才生效。

  1. CSS 变量在 .dark 下重新定义

styles.css:190-222

.dark { --background: oklch(0.141 0.005 285.823); --foreground: oklch(0.985 0 0); --card: oklch(0.21 0.006 285.885); /* ... 其他暗色 token */ }

:root 里定义了一套浅色变量,.dark 块里把同一批 CSS 变量覆盖成深色值。因为变量名一样,所以所有用 var(--background) 的地方会自动换色。

  1. 基础样式消费这些变量

styles.css:224-235

@layer base { * { border-color: var(--border); outline-color: color-mix(in oklab, var(--ring) 50%, transparent); } body { background-color: var(--background); color: var(--foreground); font-family: var(--font-sans); } }

body 的背景和文字颜色直接来自 CSS 变量,所以只要 .dark 一加,整页底色和文字色就变了。

完整链路

点击 ThemeToggle → useTheme().toggleTheme() ↓ 更新 React state + localStorage ↓ useEffect 在 <html> 上 add/remove 'dark' ↓ .dark 块里的 CSS 变量覆盖 :root 的值 ↓ body / Tailwind dark: 类自动切换颜色

所以 ThemeProvider 里的那个 useEffect 不是在“手动改很多样式”,它只是负责在 <html> 上切一个 class;真正的颜色映射全部由 CSS 变量和 Tailwind 的 dark: 变体接管。

这也是为什么它要挂在 document.documentElement(也就是 <html>)上,而不是 <body> 上——因为 Tailwind 的 @custom-variant dark (&:is(.dark *)) 是从 .dark 祖先开始向下生效的,放在 <html> 上能覆盖整个应用。