# Dark Mode
**Category**: react
**URL**: https://www.blakeui.com/en/docs/react/getting-started/dark-mode
**Source**: https://raw.githubusercontent.com/myblakebox/BlakeUI/refs/heads/main/apps/docs/content/docs/en/react/getting-started/(handbook)/dark-mode.mdx
> Add light, dark, and system theme switching to blakeUI
***
blakeUI dark mode is CSS-driven. Components read theme variables from the root element, so you do not need a blakeUI provider. Add the `dark` class or `data-theme="dark"` to `` and blakeUI will apply the dark theme.
```html
```
Keep the `bg-background` and `text-foreground` classes on your app shell so the page canvas changes with the active theme.
blakeUI's built-in light and dark themes respond to both `.light` / `.dark` classes and `data-theme="light"` / `data-theme="dark"` attributes. If you set both manually, keep the values in sync.
## Next.js with next-themes
Use [next-themes](https://github.com/pacocoursey/next-themes) when you need theme persistence, system preference support, and no flash before hydration in a Next.js app.
### Install next-themes
```bash
npm i next-themes
```
```bash
pnpm add next-themes
```
```bash
yarn add next-themes
```
```bash
bun add next-themes
```
### App Router
Create a client provider for `next-themes`.
```tsx
// app/providers.tsx
"use client";
import {ThemeProvider as NextThemesProvider} from "next-themes";
export function Providers({children}: {children: React.ReactNode}) {
return (
{children}
);
}
```
Wrap your app with the provider from the root layout. Add `suppressHydrationWarning` to `` because `next-themes` updates that element before hydration.
```tsx
// app/layout.tsx
import "./globals.css";
import {Providers} from "./providers";
export default function RootLayout({children}: {children: React.ReactNode}) {
return (
{children}
);
}
```
### Theme switcher
Use `useTheme` from `next-themes` inside a client component. Delay rendering until mount because the active theme is not known during SSR.
```tsx
// app/components/theme-switcher.tsx
"use client";
import {Button} from "@blakeui/react";
import {useTheme} from "next-themes";
import {useEffect, useState} from "react";
export function ThemeSwitcher() {
const [mounted, setMounted] = useState(false);
const {resolvedTheme, setTheme, theme} = useTheme();
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) return null;
const activeTheme = theme === "system" ? resolvedTheme : theme;
return (
);
}
```
### Pages Router
For `pages/`, wrap your application in `pages/_app.tsx`.
```tsx
// pages/_app.tsx
import "@/styles/globals.css";
import type {AppProps} from "next/app";
import {ThemeProvider as NextThemesProvider} from "next-themes";
export default function App({Component, pageProps}: AppProps) {
return (
);
}
```
## Using custom theme names
The `attribute="class"` setup works well for the built-in `light` and `dark` themes. If your custom theme CSS is written with `data-theme` selectors, configure `next-themes` to write `data-theme` instead.
```tsx
{children}
```
When you pass a custom `themes` list, include `"light"` and `"dark"` if you still want the built-in themes available.
## React with useTheme
Use blakeUI's `useTheme` hook when you are building a plain React app, such as Vite or Create React App, and do not need `next-themes`.
The hook is exported from `@blakeui/react`. It stores the selected theme in `localStorage`, resolves `"system"` from the user's OS preference, and applies both the class and `data-theme` attribute to ``.
```tsx
// src/components/theme-switcher.tsx
import {Button, useTheme} from "@blakeui/react";
export function ThemeSwitcher() {
const {resolvedTheme, setTheme, theme} = useTheme("system");
return (
);
}
```
Use one theme controller per app. In Next.js, prefer `next-themes` and its `useTheme` hook. In plain React apps, use `useTheme` from `@blakeui/react`.
## Styling for both themes
Theme-aware utilities work automatically because they read CSS variables:
```tsx
Theme-aware content
```
Use the `dark:` variant for one-off changes that only apply in dark mode:
```tsx