nextjs使用next-themes实现明亮黑暗主题切换
明亮黑暗主题
明暗主题就是整体颜色是亮色或暗色的主题, 根据用户使用场景(比如白天或夜晚), 提供切换选项来切换系统整体颜色, 让用户视觉上拥有更舒适的体验
git仓库
本章是nextjs入门课程系列的一部分, 查看以下git仓库, 并切换到extra1分支, 可查看本章代码
安装next-themes
1
| pnpm install next-themes
|
配置tailwind主题支持
1 2 3 4 5 6 7 8 9
| import type {Config} from "tailwindcss";
const config: Config = { darkMode: ['selector', '.dark'], }; export default config;
|
在layout.tsx中添加provider
jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
import {ThemeProvider} from "next-themes";
export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="en" suppressHydrationWarning> <body className={inter.className}> {/*提供主题状态*/} <ThemeProvider> <Navbar/> {children} <Footbar/> </ThemeProvider> </body> </html> ); }
|
在navbar中添加切换按钮
jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| "use client"; import {useTheme} from "next-themes";
export default function Navbar() { const {setTheme, resolvedTheme} = useTheme();
return ( <nav className={'bg-green-200 border-b border-b-gray-300 sticky w-full h-20 flex items-center'}> <div className={'flex-1'}></div> {resolvedTheme !== 'dark' ? // 切换颜色主题的按钮 <img className={'size-10'} onClick={() => setTheme('dark')} src="https://www.svgrepo.com/show/489517/mode-dark.svg" alt="to dark theme mode"/> : <img className={'size-10'} onClick={() => setTheme('light')} src="https://www.svgrepo.com/show/489519/mode-light.svg" alt="to light theme mode"/> } </nav> ) }
|
关于”use client”: 这是启用了客户端的功能, 比如js交互/浏览器storage/cookie等
查看效果:
针对黑暗模式添加样式
你是否发现了, 暗黑模式下文字样式改变了, 而有些我们已经指定了样式(className中)的没有改变.
我们可以使用dark:来配置黑暗模式下的样式
jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| "use client"; import {useTheme} from "next-themes";
export default function Navbar() {
return ( <nav className={ `bg-green-200 dark:bg-green-800 ...` }> {/*...*/} </nav> ) }
export default function Footbar() {
return ( <footer className={ `bg-gray-200 dark:bg-gray-800 ...` }> footbar </footer> ) }
|
jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
export default async function BlogPage({ params, searchParams, }: { params: { slug: string } // 接收url参数: (/blog/[slug] -> slug) searchParams: {} }) {
return ( <div className={'w-screen flex flex-row justify-center'}> {/* prose让文本中的标题有对应的样式 dark:prose-invert是让prose适配黑暗主题 */} <div className={`prose dark:prose-invert`} dangerouslySetInnerHTML={{__html: html}}> </div> </div> ) }
|
效果:
结束
谢谢观看!