I built a custom Dark Mode for React + Tailwindcss
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:
useDarkMode
Hook:Manages dark mode state using
useState
.Initializes state from
localStorage
and updates it on changes.Persists dark mode preference in
localStorage
.
DarkMode
Component:Uses
useEffect
to add or remove thedark
class on thehtml
element 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
Subscribe to my newsletter
Read articles from CODEWITHG.COM directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
CODEWITHG.COM
CODEWITHG.COM
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.