深色模式(Dark Mode)已经成为现代 Web 应用的标配功能。Tailwind CSS 提供了强大的深色模式支持,让我们能够轻松实现优雅的明暗主题切换。本节将详细介绍如何在项目中实现完善的深色模式适配。

基础配置

启用深色模式

tailwind.config.js 中配置深色模式策略:

  1. module.exports = {
  2. darkMode: 'class', // 或使用 'media'
  3. // ...其他配置
  4. }

两种模式说明:

  • class: 通过添加 dark 类名切换
  • media: 跟随系统设置自动切换

基础用法

使用 dark: 前缀来定义深色模式下的样式:

  1. <div class="bg-white dark:bg-gray-800
  2. text-gray-900 dark:text-gray-100">
  3. <h1 class="text-2xl font-bold">
  4. 标题文本
  5. </h1>
  6. <p class="text-gray-600 dark:text-gray-400">
  7. 正文内容
  8. </p>
  9. </div>

主题切换实现

手动切换方案

  1. 基础 HTML 结构:
  1. <div class="flex items-center space-x-2">
  2. <button id="theme-toggle"
  3. class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700">
  4. <!-- 亮色模式图标 -->
  5. <svg class="w-5 h-5 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
  6. <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"/>
  7. </svg>
  8. <!-- 深色模式图标 -->
  9. <svg class="w-5 h-5 block dark:hidden" fill="currentColor" viewBox="0 0 20 20">
  10. <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/>
  11. </svg>
  12. </button>
  13. <span class="text-sm text-gray-600 dark:text-gray-400">
  14. 切换主题
  15. </span>
  16. </div>
  1. JavaScript 实现:
  1. // 主题切换功能
  2. function setupThemeToggle() {
  3. const theme = localStorage.getItem('theme')
  4. const isDark = theme === 'dark' ||
  5. (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)
  6. if (isDark) {
  7. document.documentElement.classList.add('dark')
  8. }
  9. const toggle = document.getElementById('theme-toggle')
  10. toggle.addEventListener('click', () => {
  11. const isDark = document.documentElement.classList.toggle('dark')
  12. localStorage.setItem('theme', isDark ? 'dark' : 'light')
  13. })
  14. }

系统主题跟随

监听系统主题变化:

  1. // 监听系统主题变化
  2. window.matchMedia('(prefers-color-scheme: dark)')
  3. .addEventListener('change', event => {
  4. if (!localStorage.getItem('theme')) {
  5. document.documentElement.classList.toggle('dark', event.matches)
  6. }
  7. })

深色模式样式指南

颜色系统设计

  1. 建立颜色对应关系:
  1. // tailwind.config.js
  2. module.exports = {
  3. theme: {
  4. extend: {
  5. colors: {
  6. // 定义语义化的颜色变量
  7. primary: {
  8. light: '#3B82F6', // 浅色主题
  9. dark: '#60A5FA' // 深色主题
  10. },
  11. surface: {
  12. light: '#FFFFFF',
  13. dark: '#1F2937'
  14. },
  15. // ...更多颜色定义
  16. }
  17. }
  18. }
  19. }
  1. 使用自定义颜色:
  1. <button class="bg-primary-light dark:bg-primary-dark
  2. text-white
  3. px-4 py-2 rounded-lg">
  4. 主题色按钮
  5. </button>

常见组件适配

卡片组件

  1. <div class="bg-white dark:bg-gray-800
  2. shadow-lg dark:shadow-gray-900/30
  3. rounded-lg p-6">
  4. <h3 class="text-gray-900 dark:text-white font-semibold">
  5. 卡片标题
  6. </h3>
  7. <p class="mt-2 text-gray-600 dark:text-gray-400">
  8. 卡片内容描述
  9. </p>
  10. </div>

表单元素

  1. <input
  2. type="text"
  3. class="w-full px-4 py-2
  4. bg-white dark:bg-gray-700
  5. border border-gray-300 dark:border-gray-600
  6. text-gray-900 dark:text-white
  7. focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400
  8. rounded-lg"
  9. placeholder="请输入内容"
  10. />

导航栏

  1. <nav class="bg-white dark:bg-gray-800
  2. border-b border-gray-200 dark:border-gray-700">
  3. <div class="max-w-7xl mx-auto px-4">
  4. <div class="flex items-center justify-between h-16">
  5. <div class="flex items-center">
  6. <img class="h-8 w-auto" src="logo-light.svg"
  7. alt="Logo"
  8. class="block dark:hidden" />
  9. <img class="h-8 w-auto" src="logo-dark.svg"
  10. alt="Logo"
  11. class="hidden dark:block" />
  12. </div>
  13. <!-- 导航项目 -->
  14. </div>
  15. </div>
  16. </nav>

图片和媒体处理

图片适配

  1. 使用不同版本的图片:
  1. <picture>
  2. <source srcset="dark-image.jpg"
  3. media="(prefers-color-scheme: dark)" />
  4. <img src="light-image.jpg" alt="示例图片"
  5. class="rounded-lg" />
  6. </picture>
  1. SVG 图标适配:
  1. <svg class="w-6 h-6 text-gray-800 dark:text-gray-200"
  2. fill="currentColor"
  3. viewBox="0 0 24 24">
  4. <!-- 图标路径 -->
  5. </svg>

性能优化

按需加载样式

使用 CSS 变量优化样式切换:

  1. // tailwind.config.js
  2. module.exports = {
  3. theme: {
  4. extend: {
  5. colors: {
  6. primary: 'var(--color-primary)',
  7. background: 'var(--color-background)',
  8. text: 'var(--color-text)'
  9. }
  10. }
  11. }
  12. }
  1. /* global.css */
  2. :root {
  3. --color-primary: #3B82F6;
  4. --color-background: #FFFFFF;
  5. --color-text: #111827;
  6. }
  7. :root.dark {
  8. --color-primary: #60A5FA;
  9. --color-background: #1F2937;
  10. --color-text: #F9FAFB;
  11. }

预加载处理

避免主题切换时的闪烁:

  1. <!-- 在 head 标签中添加 -->
  2. <script>
  3. // 立即执行主题初始化
  4. if (localStorage.theme === 'dark' ||
  5. (!localStorage.theme &&
  6. window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  7. document.documentElement.classList.add('dark')
  8. }
  9. </script>

最佳实践

  1. 主题切换策略

    • 考虑用户偏好设置
    • 提供平滑的切换体验
    • 保存用户的选择
  2. 颜色选择原则

    • 保持适当的对比度
    • 避免纯黑色背景
    • 使用柔和的深色调
  3. 组件设计建议

    • 使用语义化的颜色变量
    • 确保所有状态都经过测试
    • 注意细节处理(阴影、边框等)
  4. 可访问性考虑

    • 确保文本对比度符合 WCAG 标准
    • 测试所有交互元素
    • 提供清晰的视觉反馈

常见问题解决

  1. 闪烁问题

    1. <!-- 添加到 head 标签中 -->
    2. <style>
    3. .no-transition * {
    4. transition: none !important;
    5. }
    6. </style>
    7. <script>
    8. document.documentElement.classList.add('no-transition')
    9. requestAnimationFrame(() => {
    10. document.documentElement.classList.remove('no-transition')
    11. })
    12. </script>
  2. 第三方组件适配 ```javascript // 为第三方组件添加深色模式支持 const darkModeConfig = { // 配置深色模式样式覆盖 }

// 根据主题动态应用样式 function applyThemeToThirdParty(isDark) { // 应用样式逻辑 } ```

总结

  • 深色模式是提升用户体验的重要特性
  • Tailwind CSS 提供了完善的深色模式支持
  • 注意性能优化和可访问性
  • 保持一致的设计语言