I built a custom Dark Mode for React + Tailwindcss
A short article to create your Dark Mode on React with Tailwindcss

CTO of Allocations.com, a finance SaaS Miami-based, I am running a YouTube channel: @codewithguillaume. With 15 years of exp. as a freelancer, consultant, and Lead Developer, I have led dozens of engineering teams across Paris, London, and Berlin. I am father of 2 and I live in Dubai.
I recently wrote an article on creating dark mode in Next.js. Today, I'm sharing an even quicker method in React.
Step 1: Install TailwindCSS and Lucide-React
Install TailwindCSS and lucide-react:
npm install tailwindcss lucide-react
# or
yarn add tailwindcss lucide-react
Step 2: Configure TailwindCSS for Dark Mode
Enable the dark mode class strategy in tailwind.config.js:
module.exports = {
darkMode: ['class'],
// other configurations...
};
Step 3: Create a Dark Mode Toggle Component
Create a DarkMode component to toggle dark mode:
"use client"
import { Moon, Sun } from "lucide-react";
import { useState, useEffect } from 'react';
export const useDarkMode = () => {
const [dark, setDark] = useState(false);
useEffect(() => {
const storedDarkMode = localStorage.getItem('dark-mode');
if (storedDarkMode) {
setDark(storedDarkMode === 'true');
}
}, []);
useEffect(() => {
localStorage.setItem('dark-mode', dark);
}, [dark]);
return [dark, setDark];
};
export default function DarkMode({ dark, setDark }) {
useEffect(() => {
if (typeof window !== "undefined") {
const root = window.document.documentElement;
if (dark) {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
}
}, [dark]);
return (
<div className="cursor-pointer" onClick={() => setDark(!dark)}>
{dark ? <Sun className="h-[1.2rem] w-[1.2rem]" /> : <Moon className="h-[1.2rem] w-[1.2rem]" />}
</div>
);
}
Here's a brief explanation of the code:
useDarkModeHook:Manages dark mode state using
useState.Initializes state from
localStorageand updates it on changes.Persists dark mode preference in
localStorage.
DarkModeComponent:Uses
useEffectto add or remove thedarkclass on thehtmlelement based on the dark mode state.Renders an icon that toggles dark mode on click (Moon for light mode, Sun for dark mode).
This setup allows for easy toggling and persistence of dark mode in a React app.
Step 4: Import your Dark Mode in your Header
You probably got a place where to import your Header.jsx — layout, main or App.jsx:
import DarkMode, { useDarkMode } from '@/components/DarkMode';
export default function Header() {
const [dark, setDark] = useDarkMode();
return (
<header className="flex items-center justify-end p-4">
<DarkMode dark={dark} setDark={setDark} />
</header>
);
}
Step 5: Leverage your style in CSS/SCSS
Update your styles to support dark mode:
body {
@apply text-black min-h-screen dark:bg-slate-900 dark:text-white;
}
EDIT: Shortest version.
// header
import DarkMode from "@/components/DarkMode";
export default function Header() {
return (
<header className="flex items-center justify-end pt-4">
<DarkMode />
</header>
);
}
// DarkMode.jsx only (using react-use)
"use client"
import { Moon, Sun } from "lucide-react";
import { useEffect, useState } from 'react';
import { useLocalStorage } from 'react-use';
export default function DarkMode() {
const [dark, setDark] = useState(false);
const [value, setValue, remove] = useLocalStorage('dark-mode');
useEffect(() => {
if (value) setDark(value);
}, [value]);
useEffect(() => {
if (typeof window !== "undefined") {
const root = window.document.documentElement;
if (dark) {
root.classList.add('dark');
} else {
root.classList.remove('dark');
}
}
localStorage.setItem('dark-mode', dark);
}, [dark]);
return (
<div className="cursor-pointer" onClick={() => setDark(!dark)}>
{dark ? <Sun className="h-[1.2rem] w-[1.2rem]" /> : <Moon className="h-[1.2rem] w-[1.2rem]" />}
</div>
);
}
And that's it! You now have a functional dark mode in your React app, using TailwindCSS and lucide-react for a smooth user experience.
Best,
Guillaume Duhan



