Themes & Dark Mode in React
Dark Mode and Theme Switching are essential modern UI features that improve user experience and accessibility.
In React, implementing dynamic themes (like light and dark modes) is simple using CSS variables, React state, or context APIs — and works seamlessly with frameworks like Tailwind CSS or Styled Components.
What is Theme / Dark Mode in React?
A theme defines the overall appearance of your app — including colors, backgrounds, typography, and spacing.
Dark mode is one of the most common themes, providing a darker color palette to reduce eye strain and improve usability in low-light environments.
React allows you to dynamically switch between themes by updating component styles, CSS variables, or global classes.
Benefits of Adding Dark Mode
- Improves UX: Reduces eye strain and adapts to user preferences.
- Modern Look: Aesthetic and professional interface.
- Accessibility: Helpful for users with light sensitivity.
- Personalization: Makes your app more user-friendly and customizable.
1. Implementing Light/Dark Mode Using React State
Let’s start with the simplest way — toggling between two themes using React’s state and className.
Example: Simple Dark Mode Toggle
import React, { useState } from "react";
import "./App.css"; // contains theme classes
function App() {
const [darkMode, setDarkMode] = useState(false);
return (
<div className={darkMode ? "app dark" : "app"}>
<h1>{darkMode ? "🌙 Dark Mode" : "☀️ Light Mode"}</h1>
<p>This is a simple example of theme switching in React.</p>
<button onClick={() => setDarkMode(!darkMode)}>
Toggle Theme
</button>
</div>
);
}
export default App;
CSS (App.css)
.app {
background-color: #ffffff;
color: #000000;
transition: all 0.3s ease-in-out;
min-height: 100vh;
text-align: center;
padding: 2rem;
}
.app.dark {
background-color: #121212;
color: #ffffff;
}
2. Using React Context for Global Theme Management
If your app has multiple components, managing themes through React Context ensures consistent behavior across the app.
Example: Global Theme Context
ThemeContext.js
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
const toggleTheme = () => {
setTheme((prev) => (prev === "light" ? "dark" : "light"));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
return useContext(ThemeContext);
}
App.js
import React from "react";
import { ThemeProvider, useTheme } from "./ThemeContext";
import "./App.css";
function ThemedComponent() {
const { theme, toggleTheme } = useTheme();
return (
<div className={`app ${theme}`}>
<h1>{theme === "dark" ? "🌙 Dark Mode" : "☀️ Light Mode"}</h1>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
export default function App() {
return (
<ThemeProvider>
<ThemedComponent />
</ThemeProvider>
);
}
Why use Context?
- Provides global theme state across all components.
- Eliminates prop drilling.
- Scales well for large apps.
3. Tailwind CSS Dark Mode Setup
If you’re using Tailwind CSS, dark mode integration is built-in and very easy to enable.
Step 1: Enable Dark Mode in tailwind.config.js
module.exports = {
darkMode: 'class', // enables dark mode via a class
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
Step 2: Add a Theme Toggle in React
import { useState } from "react";
export default function App() {
const [darkMode, setDarkMode] = useState(false);
return (
<div className={darkMode ? "dark" : ""}>
<div className="min-h-screen flex flex-col items-center justify-center bg-white dark:bg-gray-900 text-black dark:text-white transition-all">
<h1 className="text-3xl font-bold mb-4">
{darkMode ? "🌙 Dark Mode" : "☀️ Light Mode"}
</h1>
<buttononClick={() => setDarkMode(!darkMode)}
className="px-4 py-2 bg-blue-500 dark:bg-yellow-400 text-white dark:text-black rounded"
>
Toggle Theme
</button>
</div>
</div>
);
}
4. Saving Theme Preference (Local Storage)
To remember the user’s theme even after refresh:
import React, { useState, useEffect } from "react";
function App() {
const [theme, setTheme] = useState(localStorage.getItem("theme") || "light");
useEffect(() => {
localStorage.setItem("theme", theme);
document.body.className = theme;
}, [theme]);
return (
<div className="App">
<h1>{theme === "dark" ? "🌙 Dark Mode" : "☀️ Light Mode"}</h1>
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
Toggle Theme
</button>
</div>
);
}
export default App;
