使用 next-themes 两行代码为 Next.js 项目添加暗黑模式

之前写过文章介绍 React 暗黑模式的实现方式,其原理基本和目前主流的暗黑模式实现方案相似,主要用到的技术有:CSS Variables, 媒体查询, window.matchMedia, React Context 等。但是每个项目都需要重复实现会带来冗余的代码和额外的维护成本。

于是发现社区已有了封装好的方案:next-themes,口号是 Perfect Next.js dark mode in 2 lines of code. 经过试用之后发现其接入简单、功能丰富、支持自定义扩展度高、实现原理基本类似,确实能够快速的为 Next.js 项目添加暗黑模式支持。

本文介绍 next-themes 的使用方式。实现效果可以见在线演示

使用

1. 安装

bash 复制代码
npm install next-themes

2. 在 pages/_app.js 中加入 ThemeProvider

这里就是所谓的"两行代码",只需要引入 ThemeProvider 和使用 ThemeProvider 包裹组件即可。

当然其实更多的自定义样式和样式切换会需要额外的代码,但也可以使用提供的封装好的 useTheme hook 快速实现。

jsx 复制代码
import { ThemeProvider } from 'next-themes'

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp

3. 基于 [data-theme='dark'] 属性选择器改变样式

默认情况下,next-themes 会修改 html 元素上的 data-theme 属性,可以轻松地使用该属性来设置样式:

css 复制代码
:root {
  /* Your default theme */
  --background: white;
  --foreground: black;
}

[data-theme='dark'] {
  --background: black;
  --foreground: white;
}

4. 使用 useTheme 获取当前主题和改变主题

jsx 复制代码
import { useTheme } from 'next-themes'

const ThemeChanger = () => {
  const { theme, setTheme } = useTheme()

  return (
    <div>
      The current theme is: {theme}
      <button onClick={() => setTheme('light')}>Light Mode</button>
      <button onClick={() => setTheme('dark')}>Dark Mode</button>
    </div>
  )
}

Tailwind CSS 中使用方式

TailWind CSS 中是基于 dark: 来切换暗黑模式样式的,next-themes 也可以结合 TailWind CSS 一起使用。

实现效果可以看在线演示

1. 将 Tailwind 的暗黑模式配置为基于 class

javascript 复制代码
// tailwind.config.js
module.exports = {
  darkMode: 'class'
}

2. 将 data-attribute 方式改为 class

jsx 复制代码
// pages/_app.js
<ThemeProvider attribute="class">

3. 基于 dark: 来切换暗黑模式下的样式

jsx 复制代码
<h1 className="text-black dark:text-white">

更多使用方式可见next-themes 项目文档

参考链接

相关推荐
我在北京coding23 分钟前
TypeError: Cannot read properties of undefined (reading ‘queryComponents‘)
前端·javascript·vue.js
前端开发与ui设计的老司机1 小时前
UI前端与数字孪生结合实践探索:智慧物流的货物追踪与配送优化
前端·ui
全能打工人1 小时前
前端查询条件加密传输方案(SM2加解密)
前端·sm2前端加密
翻滚吧键盘2 小时前
vue绑定一个返回对象的计算属性
前端·javascript·vue.js
秃了也弱了。2 小时前
Chrome谷歌浏览器插件ModHeader,修改请求头,开发神器
前端·chrome
乆夨(jiuze)2 小时前
记录H5内嵌到flutter App的一个问题,引发后面使用fastClick,引发后面input输入框单击无效问题。。。
前端·javascript·vue.js
忧郁的蛋~3 小时前
HTML表格导出为Excel文件的实现方案
前端·html·excel
小彭努力中3 小时前
141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
前端·javascript·vue.js·交互
然我3 小时前
别再只用 base64!HTML5 的 Blob 才是二进制处理的王者,面试常考
前端·面试·html
NanLing3 小时前
【纯前端推理】纯端侧 AI 对象检测:用浏览器就能跑的深度学习模型
前端