$ pnpm add nextjs-themes
or
$ npm install nextjs-themes
or
$ yarn add nextjs-themes
$ pnpm add nextjs-themes-lite
or
$ npm install nextjs-themes-lite
or
$ yarn add nextjs-themes-lite
Note:
r18gs
is a peer dependency
To add dark mode support, modify _app.js
as follows:
import { ThemeSwitcher } from "nextjs-themes";
function MyApp({ Component, pageProps }) {
return (
<>
<ThemeSwitcher forcedTheme={Component.theme} />
<Component {...pageProps} />
</>
);
}
export default MyApp;
⚡🎉Boom! Dark mode is ready in just a couple of lines!
app
router (Server Components)Update app/layout.jsx
to add ThemeSwitcher
from nextjs-themes
:
// app/layout.jsx
import { ThemeSwitcher } from "nextjs-themes";
export default function Layout({ children }) {
return (
<html lang="en">
<head />
<body>
<ThemeSwitcher />
{children}
</body>
</html>
);
}
Woohoo! Multiple theme modes with Server Components support!
Next.js app supports dark mode, including System preference with prefers-color-scheme
. The theme is synced between tabs, modifying the data-theme
attribute on the html
element:
:root {
--background: white;
--foreground: black;
}
[data-theme="dark"] {
--background: black;
--foreground: white;
}
Configuring nextjs-themes is super simple. You can use following props to configure the main ThemeSwitcher
component.
export interface ThemeSwitcherProps {
/**
* Forced theme name for the current page
* @see [Force per page theme and color-scheme](https://github.com/react18-tools/nextjs-themes?tab=readme-ov-file#force-per-page-theme-and-color-scheme)
*/
forcedTheme?: string;
/**
* Forced color scheme for the current page
* @see [Force per page theme and color-scheme](https://github.com/react18-tools/nextjs-themes?tab=readme-ov-file#force-per-page-theme-and-color-scheme)
*/
forcedColorScheme?: ColorSchemeType;
/**
* CSS selector for the target element to apply the theme.
* Use this to specify a different target element than the default (html or documentElement).
* This is particularly useful for controlling the theme of different parts of the page independently.
*/
targetSelector?: string;
/**
* The transition property to enforce on all elements, preventing unwanted transitions during theme changes.
* @example 'background .3s'
* @defaultValue 'none'
*/
themeTransition?: string;
/**
* Provide a styles object imported from CSS/SCSS modules if you are using these modules to define theme and color-scheme classes.
* All classes applied to the target are modified using the styles object as follows:
* `if (styles) classes = classes.map(cls => styles[cls] ?? cls);`
*/
styles?: Record<string, string>;
/** The nonce value for your Content Security Policy. */
nonce?: string;
}
To augment the functionality, we also provide ForceTheme
and ForceColorScheme
components that effectively apply the forcedTheme
and forcedColorScheme
props via internal state variable. Please note that the props passed to the ThemeSwitcher
has the highest priority.
Show different images based on the current theme:
import Image from "next/image";
import { useTheme } from "nextjs-themes/hooks";
function ThemedImage() {
const { resolvedTheme } = useTheme();
const src = resolvedTheme === "light" ? "/light.png" : "/dark.png";
return <Image src={src} width={400} height={400} />;
}
export default ThemedImage;
The useTheme
hook provides theme information and allows changing the theme:
import { useTheme } from "nextjs-themes/hooks";
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>
);
};
The useTheme
hook returns the following object:
interface UseThemeYield {
theme: string;
darkTheme: string;
lightTheme: string;
colorSchemePref: ColorSchemeType;
systemColorScheme: ResolvedColorSchemeType;
resolvedColorScheme: ResolvedColorSchemeType;
resolvedTheme: string;
setTheme: (theme: string) => void;
setDarkTheme: (darkTheme: string) => void;
setLightTheme: (lightTheme: string) => void;
setThemeSet: (themeSet: { darkTheme: string; lightTheme: string }) => void;
setColorSchemePref: (colorSchemePref: ColorSchemeType) => void;
toggleColorScheme: (skipSystem?: boolean) => void;
setForcedTheme: (forcedTheme: string) => void;
setForcedColorScheme: (forcedColorScheme: ColorSchemeType) => void;
}
import { ForceTheme } from "nextjs-themes/force-theme";
function MyPage() {
return (
<>
<ForceTheme theme="my-theme" />
...
</>
);
}
export default MyPage;
If you are using TypeScript and have not set nodeResolution to
Bundler
orNode16
orNodeNext
, you need to import fromnextjs-themes/client/force-theme
For the pages router, you have two options. The first option is the same as the app router, and the second option, which is compatible with next-themes
, involves adding the theme
property to your page component like this:
function MyPage() {
return <>...</>;
}
MyPage.theme = "my-theme";
export default MyPage;
Similarly, you can force a color scheme. This will apply your defaultDark
or defaultLight
theme, which can be configured via hooks.
Next Themes works with any library. For Styled Components, createGlobalStyle
in your custom App:
// pages/_app.js
import { createGlobalStyle } from "styled-components";
import { ThemeSwitcher } from "nextjs-themes";
const GlobalStyle = createGlobalStyle`
:root {
--fg: #000;
--bg: #fff;
}
[data-theme="dark"] {
--fg: #fff;
--bg: #000;
}
`;
function MyApp({ Component, pageProps }) {
return (
<>
<GlobalStyle />
<ThemeSwitcher forcedTheme={Component.theme} />
<Component {...pageProps} />
</>
);
}
In tailwind.config.js
, set the dark mode property to class:
// tailwind.config.js
module.exports = {
darkMode: "class",
};
⚡🎉Ready to use dark mode in Tailwind!
Caution: Your class must be
"dark"
, which is the default value used in this library. Tailwind requires the class name"dark"
for dark-theme.
Use dark-mode specific classes:
<h1 className="text-black dark:text-white">
Please consider enrolling in our courses or sponsoring our work.
with 💖 by Mayank Kumar Chaudhari