2026年6月21日 01:55

Tailwind CSS 深色模式怎么实现,常用 dark 类有哪些?

Tailwind CSS 做深色模式,核心不是写两套 CSS,而是选好触发方式,然后在需要变化的地方加 dark: 变体。常见写法大概分两类:跟随系统的 media,以及由页面上的 .dark 或自定义选择器控制的 class/selector。前者省事,后者更适合带主题切换按钮的产品。

先选深色模式触发方式

media 使用浏览器的 prefers-color-scheme,用户系统是深色,页面就走深色样式。

js
export default { darkMode: 'media' }

适合页面不需要主题切换按钮、希望完全尊重系统设置的情况。缺点是用户不能在站内单独选择浅色或深色。

如果需要按钮切换,推荐用选择器控制。旧项目里常见 class,新一点的 Tailwind v3.4+ 更推荐 selector

js
export default { darkMode: 'selector' }

页面上加:

html
<html class="dark">

Tailwind v4 更偏 CSS-first。如果要用 .darkdata-theme 控制,可以在 CSS 里自定义变体:

css
@import 'tailwindcss'; @custom-variant dark (&:where(.dark, .dark *));

或者:

css
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));

常用 dark: 类怎么写

Tailwind 的深色模式不是单独的一套类,而是在原有工具类前面加 dark:

html
<div class="rounded-xl border border-slate-200 bg-white p-6 text-slate-900 shadow-sm dark:border-slate-800 dark:bg-slate-950 dark:text-slate-100 dark:shadow-slate-950/40"> <h2 class="text-lg font-semibold text-slate-900 dark:text-white">账户设置</h2> <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">这里会跟随当前主题切换颜色。</p> </div>

项目里最常用的是背景、文字、边框、阴影、hover、表单占位文字、分割线和 focus ring:

html
<input class="border-slate-300 bg-white text-slate-900 placeholder:text-slate-400 focus:ring-blue-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:placeholder:text-slate-500 dark:focus:ring-blue-400" />

实际写组件时,不要所有颜色都硬编码成黑白。深色模式最舒服的搭配通常是深灰背景、浅灰文字、略低对比的边框。

用 JS 和 localStorage 保存用户选择

手动切换时,至少要处理三种状态:浅色、深色、跟随系统。

js
function applyTheme(theme) { const root = document.documentElement const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches const shouldUseDark = theme === 'dark' || (!theme && systemDark) root.classList.toggle('dark', shouldUseDark) } const savedTheme = localStorage.getItem('theme') applyTheme(savedTheme) function setTheme(theme) { if (theme) localStorage.setItem('theme', theme) else localStorage.removeItem('theme') applyTheme(theme) }

如果用 data-theme,把 classList.toggle('dark') 换成设置属性即可。

React / Vue 接入和避免闪烁

React 或 Vue 的切换按钮可以放在组件里,但首次应用主题最好用一段很短的内联脚本提前做。否则页面会先按亮色渲染,JavaScript 加载后再切深色,产生 FOUC 闪烁。

html
<script> try { const theme = localStorage.getItem('theme') const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches if (theme === 'dark' || (!theme && systemDark)) { document.documentElement.classList.add('dark') } } catch (e) {} </script>

SSR 框架里还要注意服务端无法直接读取 localStorage。可以用 cookie 保存主题,或者接受首次渲染由内联脚本修正。

对比度和检查清单

深色模式不是把颜色反过来。正文建议至少满足 WCAG 常规文本 4.5:1 的对比度。按钮 hover、focus ring、错误提示、禁用态、图标、表格边框都要单独看。

实现前可以按这个清单过一遍:确认策略,确认 Tailwind 版本,根节点统一用 .darkdata-theme,常用类补齐,保存用户选择,提前执行脚本避免闪烁,测试对比度,测试系统主题变化。

Tailwind 的深色模式写起来不难,难的是别漏状态。触发方式选对,组件里坚持用 dark: 写差异,再把本地存储、FOUC 和对比度检查补上,这套方案就能稳定用在真实项目里。

标签:Tailwind CSS