前言 #
深色模式 (Dark Mode) 在近代使用者裝置上顯得越來越普遍,iOS、MacOS、Android、Windows 在更新上都不約而同的推出。長時間暴露在高亮度的白底介面中,往往容易造成眼睛疲勞、乾澀,甚至影響專注力與睡眠品質。為了改善這樣的使用體驗,深色模式誕生了。
或許不見得要一開始就導入深色模式,但若有提供這個啟閉選項,在使用者的體驗上肯定是更好的。想先列出幾個優點以及需要顧慮的點。
優點:
- 減輕低光環境閱讀疲勞,提升夜間舒適度
- OLED 螢幕上較省電
- 提升視覺吸引力
缺點:
- 高光環境下可讀性下降
- 長篇文章閱讀感到不適
Changelog:
2025/10/07 更新:安裝路徑修正、安裝方式更完善說明
設置深色模式 #
這邊以 Next.js 作為示範,若有需要在 Vite、Astro、Remix 上實作,可以參考 Shadcn/ui Dark Mode。
-
專案中安裝
next-themes、Shadcn/ui 的Button、Dropdown Menu、lucide-iconnpm install next-themes npx shadcn@latest add @animate-ui/icons-icon npx shadcn@latest add button dropdown-menu -
在
components資料夾,新增theme-provider.tsx檔案,並加上以下程式碼若沒有
components資料夾,可以在專案目錄中新增"use client" import * as React from "react" import { ThemeProvider as NextThemesProvider } from "next-themes" export function ThemeProvider({ children, ...props }: React.ComponentProps<typeof NextThemesProvider>) { return <NextThemesProvider {...props}>{children}</NextThemesProvider> }
-
修改
app/layout.tsx在 import 區域增加
import { ThemeProvider } from "@/components/theme-provider"
並且在
export default function RootLayout(...){return(...)}中修改export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="zh-Hant" suppressHydrationWarning> <body className={`${geistSans.variable} ${geistMono.variable} antialiased`} > <ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange > {children} </ThemeProvider> </body> </html> ); }
-
找個合適的位置放置深淺色模式切換。在這邊的範例中,我將切換按鈕放在 next.js logo 下方。
-
打開
app/page.tsx,並且將必要的 import 載入import { useTheme } from "next-themes" -
找到
export function ...{}當中加入這個 React Hook,用途是後面要 onclick 動作時可以觸發const { setTheme } = useTheme()
-
在
return(<html>...</html>)中加入深淺色模式切換按鈕和 Menu<DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline" size="icon"> <Sun className="h-[1.2rem] w-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" /> <Moon className="absolute h-[1.2rem] w-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" /> <span className="sr-only">Toggle theme</span> </Button> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuItem onClick={() => setTheme("light")}> Light </DropdownMenuItem> <DropdownMenuItem onClick={() => setTheme("dark")}> Dark </DropdownMenuItem> <DropdownMenuItem onClick={() => setTheme("system")}> System </DropdownMenuItem> </DropdownMenuContent> </DropdownMenu>
-
執行
npm run dev測試效果
-
小結 #
今天示範如何完成深淺色模式的設置,並且觀察在切換深淺色時使用 onClick 事件的運作方式。其實不只 dropdown menu,還能夠透過 switch、icon 等不同元件來實現切換。以上算是最基礎的範例,幫助大家建立概念。
明天我們將進一步探索 Animate UI 的文字動畫效果,看看如何讓文字活起來~