dark: 前缀仅硬编码映射系统偏好,不支持多主题;必须用 darkmode: 'class' + @layer base 定义 css 变量,并通过 data-theme 控制主题切换。

必须用 darkMode: 'class' + CSS 变量 + @layer base,dark: 前缀本身不支持多主题,只认 class="dark" 或系统偏好。
为什么 dark: 不能用于多主题切换
dark: 是 Tailwind 对 prefers-color-scheme: dark 的硬编码映射,不是通用主题开关。哪怕你写 data-theme="dark",dark:bg-gray-900 也完全不生效。混用 dark: 和 data-theme 会导致 DevTools 里样式忽明忽暗——因为两套机制在竞争同一元素的渲染权。
-
darkMode: 'media'→ 完全由系统控制,JS 切换无效 -
darkMode: true或''或未声明 → 编译器直接剔除所有dark:类,连 warning 都不抛 - 只有
darkMode: 'class'才允许 JS 通过document.documentElement.classList.toggle('dark')控制,且是 SSR(如 Next.js/Nuxt)首屏不闪的前提
如何让 data-theme="light"、"dark"、"sepia" 同时生效
核心是把变量挂到 :root 和带 [data-theme] 的作用域下,并统一用语义名(如 --color-bg),而不是靠 Tailwind 自动生成色阶。
- 所有主题变量必须写在
@layer base块内,否则会被 Tailwind 默认样式覆盖 -
data-theme必须设在上,设在或组件内会断继承链 - 首次渲染前需内联默认值,比如在
里加<style>:root { --color-bg: #fff; --color-text: #1f2937; }</style>,否则 JS 执行前浏览器按未定义变量渲染一帧,出现白屏或错色 - 变量名必须严格一致:写
var(--color-bg),不能有空格或全角字符;var( --color-bg )会编译失败
tailwind.config.js 中怎么桥接 CSS 变量
不是重写颜色数组,而是把变量名“透传”进工具类生成逻辑。重点在 theme.extend.colors 和 safelist 配置。
- 在
theme.extend.colors里写:bg: 'var(--color-bg)'、text: 'var(--color-text)',而不是blue: '#3b82f6' - 必须加
safelist,否则 JIT 编译会删掉bg-[var(--color-bg)]这类动态类:safelist: [/^bg-\[.*\]$/, /^text-\[.*\]$/] - 不要用第三方插件(如
tailwindcss-theming):它们劫持theme.colors解析,导致 DevTools 无法追踪最终变量值,且 Tailwind 4 升级后大概率失效 - 若要支持
bg-[var(--color-bg)]写法,确保模板中真实使用过该 class,否则 JIT 不生成对应 CSS 规则
切换主题时最容易被忽略的细节
变量初始化时机比切换函数更重要。JS 执行 document.documentElement.setAttribute('data-theme', 'dark') 时,如果 CSS 文件还没解析完,浏览器会先按旧变量渲染一帧。这不是 bug,是浏览器加载顺序决定的。
- 内联默认变量 + 统一命名(别混用
--primary和--color-primary)比写十个setTheme()函数更关键 - 第三方 UI 库(如 Headless UI)默认只输出
dark:类,不会响应data-theme,需手动包裹或重写其 class 逻辑 - 深色模式本身只是多主题之一,把它和
light、sepia平等对待,全部走 CSS 变量,才能真正解耦
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











