使用 Tailwind 为网站添加深色模式

深色模式不仅仅是一种趋势——它已成为用户的期望。然而许多开发者却将其实现过度复杂化。使用 Tailwind CSS,为网站添加深色模式只需几行代码,无需任何框架依赖。
本教程涵盖自动深色模式(遵循系统偏好)和手动切换(具有用户偏好持久化)两种方式。您将学会使用 Tailwind 内置的 dark 变体在几分钟内实现任一方法。
关键要点
- Tailwind 的
dark:
变体通过最少配置即可启用深色模式 - 系统驱动的深色模式无需 JavaScript 即可自动工作
- 手动切换让用户控制其查看偏好
- localStorage 防止页面加载时的主题闪烁
Tailwind CSS 中深色模式的工作原理
dark: 变体详解
Tailwind CSS 提供了 dark:
变体,可在深色模式激活时有条件地应用样式。只需在任何实用类前添加 dark:
前缀即可定义其深色模式外观:
<div class="bg-white dark:bg-gray-900">
<h1 class="text-gray-900 dark:text-white">Hello World</h1>
<p class="text-gray-600 dark:text-gray-400">
This text adapts to your theme preference
</p>
</div>
默认情况下,Tailwind 使用 prefers-color-scheme
CSS 媒体查询来检测用户的系统偏好。无需配置——开箱即用。
系统驱动的深色模式(自动)
使用 prefers-color-scheme
最简单的深色模式实现无需任何 JavaScript。当用户的操作系统设置为深色模式时,Tailwind 会自动应用深色模式实用类:
<!-- 此卡片在浅色模式下为白色,在深色模式下为深灰色 -->
<article class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-lg">
<h2 class="text-xl font-bold text-gray-900 dark:text-white">
Automatic Dark Mode
</h2>
<p class="mt-2 text-gray-600 dark:text-gray-300">
This component respects your system theme preference
</p>
</article>
这种方法立即生效,但有一个限制:用户无法在您的网站上专门覆盖其系统偏好。
Discover how at OpenReplay.com.
手动深色模式切换
基于类的实现
要让用户拥有控制权,需配置 Tailwind 在父元素上使用 .dark
类。对于 Tailwind CSS v3.4 及更高版本,请在 CSS 中添加:
@import "tailwindcss";
/* 适用于 Tailwind CSS v4+ */
@custom-variant dark (&:where(.dark, .dark *));
对于早期版本的 Tailwind(v3.x),在 tailwind.config.js
中配置:
module.exports = {
darkMode: 'class',
// ... 配置的其余部分
}
现在当父元素上存在 dark
类时,深色模式即被激活:
<html class="dark">
<body>
<div class="bg-white dark:bg-black">
<!-- 深色模式已激活 -->
</div>
</body>
</html>
使用以下 JavaScript 切换深色模式:
// 切换深色模式
document.documentElement.classList.toggle('dark');
数据属性方法
一些开发者更喜欢使用数据属性进行主题管理。配置 Tailwind 使用 data-theme
:
@import "tailwindcss";
/* 适用于 Tailwind CSS v4+ */
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
然后通过属性控制深色模式:
<html data-theme="dark">
<body>
<div class="bg-white dark:bg-black">
<!-- 当 data-theme="dark" 时深色模式激活 -->
</div>
</body>
</html>
持久化用户偏好
localStorage 实现
用户期望其主题选择能够持久化。以下是一个完整的解决方案,既能记住偏好又能遵循系统默认设置:
// 检查已保存的偏好或默认使用系统偏好
function getThemePreference() {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
return savedTheme;
}
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
}
// 在加载时应用主题
function applyTheme(theme) {
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}
// 初始化主题
applyTheme(getThemePreference());
// 主题切换函数
function toggleTheme() {
const currentTheme = document.documentElement.classList.contains('dark')
? 'dark'
: 'light';
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
applyTheme(newTheme);
localStorage.setItem('theme', newTheme);
}
为防止页面加载时出现错误主题的闪烁,请在 <head>
中添加此内联脚本:
<script>
// 防止 FOUC(无样式内容闪烁)
if (localStorage.theme === 'dark' ||
(!localStorage.theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
</script>
使用 Tailwind 实现深色模式的最佳实践
性能:将主题检测脚本放在 <head>
中以防止布局偏移。上述内联脚本在页面渲染前执行。
可访问性:确保两种主题都有足够的颜色对比度。深色模式不仅仅是颜色反转——要通过适当的对比度比例保持可读性(WCAG AA 标准建议普通文本为 4.5:1)。
测试:在开发过程中始终测试两种主题。使用浏览器开发工具快速切换 prefers-color-scheme
,无需更改系统设置。
颜色一致性:系统性地使用 Tailwind 的色彩调色板。例如,如果您使用 gray-100
作为浅色背景,可考虑使用 gray-800
或 gray-900
作为深色模式的等效色。
结论
使用 Tailwind CSS 实现深色模式只需最少的代码且无需外部依赖。无论您选择系统驱动还是手动切换,dark 变体都使主题感知样式变得简单直接。从自动深色模式开始以保持简单,然后在用户需要更多查看体验控制时添加手动控件。
常见问题
可以,您可以实现一个三向切换,提供浅色、深色和系统选项。将用户选择存储在 localStorage 中,并检查他们是否选择了系统模式以遵循操作系统偏好。
对于简单调整使用 CSS 滤镜,或提供替代图像源。对于图标,考虑在 SVG 中使用 currentColor 以便它们继承文本颜色,或使用 Tailwind 实用类应用不透明度调整。
绝对可以。dark 变体适用于任何 Tailwind 实用类,包括在配置中定义的自定义颜色。只需在任何类前添加 dark: 前缀即可在深色模式下有条件地应用它。
影响很小。dark 变体只添加 CSS 规则,不会产生 JavaScript 开销。主要考虑是通过在文档头部早期加载主题检测脚本来防止无样式内容的闪烁。
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.