深色模式(Dark Mode)已经成为现代 Web 应用的标配功能。Tailwind CSS 提供了强大的深色模式支持,让我们能够轻松实现优雅的明暗主题切换。本节将详细介绍如何在项目中实现完善的深色模式适配。
基础配置
启用深色模式
在 tailwind.config.js
中配置深色模式策略:
javascript
module.exports = {
darkMode: 'class', // 或使用 'media'
// ...其他配置
}
两种模式说明:
class
: 通过添加dark
类名切换media
: 跟随系统设置自动切换
基础用法
使用 dark:
前缀来定义深色模式下的样式:
html
<div class="bg-white dark:bg-gray-800
text-gray-900 dark:text-gray-100">
<h1 class="text-2xl font-bold">
标题文本
</h1>
<p class="text-gray-600 dark:text-gray-400">
正文内容
</p>
</div>
主题切换实现
手动切换方案
- 基础 HTML 结构:
html
<div class="flex items-center space-x-2">
<button id="theme-toggle"
class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700">
<!-- 亮色模式图标 -->
<svg class="w-5 h-5 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"/>
</svg>
<!-- 深色模式图标 -->
<svg class="w-5 h-5 block dark:hidden" fill="currentColor" viewBox="0 0 20 20">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
</svg>
</button>
<span class="text-sm text-gray-600 dark:text-gray-400">
切换主题
</span>
</div>
- JavaScript 实现:
javascript
// 主题切换功能
function setupThemeToggle() {
const theme = localStorage.getItem('theme')
const isDark = theme === 'dark' ||
(!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)
if (isDark) {
document.documentElement.classList.add('dark')
}
const toggle = document.getElementById('theme-toggle')
toggle.addEventListener('click', () => {
const isDark = document.documentElement.classList.toggle('dark')
localStorage.setItem('theme', isDark ? 'dark' : 'light')
})
}
系统主题跟随
监听系统主题变化:
javascript
// 监听系统主题变化
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', event => {
if (!localStorage.getItem('theme')) {
document.documentElement.classList.toggle('dark', event.matches)
}
})
深色模式样式指南
颜色系统设计
- 建立颜色对应关系:
javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
// 定义语义化的颜色变量
primary: {
light: '#3B82F6', // 浅色主题
dark: '#60A5FA' // 深色主题
},
surface: {
light: '#FFFFFF',
dark: '#1F2937'
},
// ...更多颜色定义
}
}
}
}
- 使用自定义颜色:
html
<button class="bg-primary-light dark:bg-primary-dark
text-white
px-4 py-2 rounded-lg">
主题色按钮
</button>
常见组件适配
卡片组件
html
<div class="bg-white dark:bg-gray-800
shadow-lg dark:shadow-gray-900/30
rounded-lg p-6">
<h3 class="text-gray-900 dark:text-white font-semibold">
卡片标题
</h3>
<p class="mt-2 text-gray-600 dark:text-gray-400">
卡片内容描述
</p>
</div>
表单元素
html
<input
type="text"
class="w-full px-4 py-2
bg-white dark:bg-gray-700
border border-gray-300 dark:border-gray-600
text-gray-900 dark:text-white
focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400
rounded-lg"
placeholder="请输入内容"
/>
导航栏
html
<nav class="bg-white dark:bg-gray-800
border-b border-gray-200 dark:border-gray-700">
<div class="max-w-7xl mx-auto px-4">
<div class="flex items-center justify-between h-16">
<div class="flex items-center">
<img class="h-8 w-auto" src="logo-light.svg"
alt="Logo"
class="block dark:hidden" />
<img class="h-8 w-auto" src="logo-dark.svg"
alt="Logo"
class="hidden dark:block" />
</div>
<!-- 导航项目 -->
</div>
</div>
</nav>
图片和媒体处理
图片适配
- 使用不同版本的图片:
html
<picture>
<source srcset="dark-image.jpg"
media="(prefers-color-scheme: dark)" />
<img src="light-image.jpg" alt="示例图片"
class="rounded-lg" />
</picture>
- SVG 图标适配:
html
<svg class="w-6 h-6 text-gray-800 dark:text-gray-200"
fill="currentColor"
viewBox="0 0 24 24">
<!-- 图标路径 -->
</svg>
性能优化
按需加载样式
使用 CSS 变量优化样式切换:
javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: 'var(--color-primary)',
background: 'var(--color-background)',
text: 'var(--color-text)'
}
}
}
}
css
/* global.css */
:root {
--color-primary: #3B82F6;
--color-background: #FFFFFF;
--color-text: #111827;
}
:root.dark {
--color-primary: #60A5FA;
--color-background: #1F2937;
--color-text: #F9FAFB;
}
预加载处理
避免主题切换时的闪烁:
html
<!-- 在 head 标签中添加 -->
<script>
// 立即执行主题初始化
if (localStorage.theme === 'dark' ||
(!localStorage.theme &&
window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
}
</script>
最佳实践
-
主题切换策略
- 考虑用户偏好设置
- 提供平滑的切换体验
- 保存用户的选择
-
颜色选择原则
- 保持适当的对比度
- 避免纯黑色背景
- 使用柔和的深色调
-
组件设计建议
- 使用语义化的颜色变量
- 确保所有状态都经过测试
- 注意细节处理(阴影、边框等)
-
可访问性考虑
- 确保文本对比度符合 WCAG 标准
- 测试所有交互元素
- 提供清晰的视觉反馈
常见问题解决
- 闪烁问题
html
<!-- 添加到 head 标签中 -->
<style>
.no-transition * {
transition: none !important;
}
</style>
<script>
document.documentElement.classList.add('no-transition')
requestAnimationFrame(() => {
document.documentElement.classList.remove('no-transition')
})
</script>
- 第三方组件适配
javascript
// 为第三方组件添加深色模式支持
const darkModeConfig = {
// 配置深色模式样式覆盖
}
// 根据主题动态应用样式
function applyThemeToThirdParty(isDark) {
// 应用样式逻辑
}
总结
- 深色模式是提升用户体验的重要特性
- Tailwind CSS 提供了完善的深色模式支持
- 注意性能优化和可访问性
- 保持一致的设计语言