在 React 项目中使用 tailwindcss 添加暗黑模式

暗黑模式是一项重要的无障碍功能,在长时间编码或在弱光环境下工作时,暗黑模式能够有效缓解眼部疲劳,甚至可以在 OLED 屏幕上节省电量,让你的网站呈现现代感十足且视觉上更具吸引力的外观。本文将探讨如何在 React 项目中使用 tailwindcss 添加暗黑模式。

前置准备

在开始之前,我们需要进行以下准备:

  • 一个 React 项目。可以使用 Vite 或者 Next.js 创建一个新的 React 项目,也可以使用已有的项目。
  • 已在项目中安装并配置 Tailwind CSS。如果尚未完成此操作,可以查看 Tailwind CSS 官方文档进行配置。

步骤 1: 在 Tailwind CSS 中配置暗黑模式

在引入 tailwindcss 的全局 CSS 文件中进行主题样式配置:

css 复制代码
@import "tailwindcss";

@custom-variant dark (&:is(.dark *));

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}

:root {
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);
}

.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
}

@layer base {
  body {
    @apply bg-background text-foreground;
  }
}

步骤 2: 创建主题 Context 和 Provider

为了在整个应用程序中全局管理主题状态,这里使用了 React 的 Context API,这种方法可以让任何组件都能轻松的访问和更新当前主题。

tsx 复制代码
// components/theme-provider.tsx
import { createContext, useContext, useEffect, useState } from "react"

type Theme = "dark" | "light"

type ThemeProviderProps = {
  children: React.ReactNode
  defaultTheme?: Theme
  storageKey?: string
}

type ThemeProviderState = {
  theme: Theme
  setTheme: (theme: Theme) => void
}

const initialState: ThemeProviderState = {
  theme: "light",
  setTheme: () => null,
}

const ThemeProviderContext = createContext<ThemeProviderState>(initialState)

export function ThemeProvider({
  children,
  defaultTheme = "light",
  storageKey = "vite-ui-theme",
  ...props
}: ThemeProviderProps) {
  const [theme, setTheme] = useState<Theme>(
    () => (localStorage.getItem(storageKey) as Theme) || defaultTheme
  )

  useEffect(() => {
    const root = window.document.documentElement
    root.classList.remove("light", "dark")
    root.classList.add(theme)
  }, [theme])

  const value = {
    theme,
    setTheme: (theme: Theme) => {
      localStorage.setItem(storageKey, theme)
      setTheme(theme)
    },
  }

  return (
    <ThemeProviderContext.Provider {...props} value={value}>
      {children}
    </ThemeProviderContext.Provider>
  )
}

export const useTheme = () => {
  const context = useContext(ThemeProviderContext)

  if (context === undefined)
    throw new Error("useTheme must be used within a ThemeProvider")

  return context
}

步骤 3: 创建一个主题切换组件

tsx 复制代码
// components/mode-toggle.tsx
import { useTheme } from "@/components/theme-provider"

const SunIcon = () => (
  <svg
    className="h-6 w-6 text-yellow-500"
    fill="none"
    stroke="currentColor"
    viewBox="0 0 24 24"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M12 3v1m0 16v1m9-9h1M3 12H2m15.325-4.675l.707-.707M6.071 18.071l-.707.707M17.325 17.325l.707.707M6.071 6.071l-.707-.707"
    ></path>
  </svg>
)

const MoonIcon = () => (
  <svg
    className="h-6 w-6 text-gray-500"
    fill="none"
    stroke="currentColor"
    viewBox="0 0 24 24"
    xmlns="http://www.w3.org/2000/svg"
  >
    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
    ></path>
  </svg>
)

export function ModeToggle() {
  const { theme, setTheme } = useTheme()

  const toggleTheme = () => {
    if (theme === "dark") {
      setTheme("light")
    } else {
      setTheme("dark")
    }
  }

  return (
    <button
      onClick={toggleTheme}
      className="bg-primary text-primary-foreground rounded-md p-2 shadow-xs"
    >
      {theme === "light" ? <SunIcon /> : <MoonIcon />}
    </button>
  )
}

步骤 4:将 ThemeProvider 集成到你的应用程序中

tsx 复制代码
// App.tsx
import { ThemeProvider } from "@/components/theme-provider"
import { ModeToggle } from "@/components/mode-toggle"

function App() {
  return (
    <ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
      <div className="flex min-h-svh flex-col items-center justify-center">
        <ModeToggle />
      </div>
    </ThemeProvider>
  )
}

export default App

步骤 5:使用 Tailwind CSS 应用暗黑模式样式

在写 className 的时候使用 dark: 前缀就可以轻松添加暗黑模式样式。比如 dark:bg-gray-900

总结

网站实现暗黑模式(Dark Mode)的必要性已从设计趋势逐渐转变为用户体验的核心需求。本文通过 Tailwind CSS 内置的 dark 变体和 React 的 Context API,实现了暗黑模式主题的切换功能,这一功能可以显著提升用户体验并且让你的网站变得很酷。

相关推荐
胡gh1 分钟前
什么是瀑布流?用大白话给你讲明白!
前端·javascript·面试
universe_016 分钟前
day22|学习前端ts语言
前端·笔记
teeeeeeemo10 分钟前
一些js数组去重的实现算法
开发语言·前端·javascript·笔记·算法
Zz_waiting.11 分钟前
Javaweb - 14.1 - 前端工程化
前端·es6
掘金安东尼13 分钟前
前端周刊第426期(2025年8月4日–8月10日)
前端·javascript·面试
Abadbeginning14 分钟前
FastSoyAdmin导出excel报错‘latin-1‘ codec can‘t encode characters in position 41-54
前端·javascript·后端
ZXT15 分钟前
WebAssembly
前端
卢叁16 分钟前
Flutter开发环境安装指南
前端·flutter
curdcv_po34 分钟前
Three.js,闲谈3D——智慧XX
前端
A5rZ1 小时前
css leak -- justctf 2025 Simple Tasks
前端·css·tensorflow