1

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

基础配置

启用深色模式

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

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

两种模式说明:

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

基础用法

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

<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>

主题切换实现

手动切换方案

  1. 基础 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>
  1. 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')
  })
}

系统主题跟随

监听系统主题变化:

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

深色模式样式指南

颜色系统设计

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

常见组件适配

卡片组件

<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>

表单元素

<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="请输入内容"
/>

导航栏

<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>

图片和媒体处理

图片适配

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

性能优化

按需加载样式

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

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: 'var(--color-primary)',
        background: 'var(--color-background)',
        text: 'var(--color-text)'
      }
    }
  }
}
/* global.css */
:root {
  --color-primary: #3B82F6;
  --color-background: #FFFFFF;
  --color-text: #111827;
}

:root.dark {
  --color-primary: #60A5FA;
  --color-background: #1F2937;
  --color-text: #F9FAFB;
}

预加载处理

避免主题切换时的闪烁:

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

最佳实践

  1. 主题切换策略

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

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

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

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

常见问题解决

  1. 闪烁问题

    <!-- 添加到 head 标签中 -->
    <style>
      .no-transition * {
     transition: none !important;
      }
    </style>
    <script>
      document.documentElement.classList.add('no-transition')
      requestAnimationFrame(() => {
     document.documentElement.classList.remove('no-transition')
      })
    </script>
  2. 第三方组件适配

    // 为第三方组件添加深色模式支持
    const darkModeConfig = {
      // 配置深色模式样式覆盖
    }
    
    // 根据主题动态应用样式
    function applyThemeToThirdParty(isDark) {
      // 应用样式逻辑
    }

总结

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

Devlive开源社区
1.1k 声望29 粉丝

我们是专注于开源项目的社区,在这里您可以发现最新、最伟大的开源项目并参与其中,共同促进开源生态的繁荣与发展。