āđāļื่āļāđāļŦāļĄ? āļัāļāđāļ§็āļāļี่āļŠāļ§่āļēāļāļ้āļēāļāļāļāļēāļĨ้āļē ðĩðŦ āļ้āļēāļุāļāļāļĒāļēāļāđāļŦ้āļู้āđāļ้āđāļĨืāļāļāđāļ้āļ§่āļēāļāļĒāļēāļāđāļ้ āđāļŦāļĄāļāļŠāļ§่āļēāļ (Light Mode) āļŦāļĢืāļ āđāļŦāļĄāļāļĄืāļ (Dark Mode) āđāļ Next.js āđāļĢāļēāļĄีāļ§ิāļีāļ่āļēāļĒāđ āđāļŦ้āļุāļāļĨāļāļāļāļģ!
āđāļāļāļāļāļ§āļēāļĄāļี้ āđāļĢāļēāļāļ°āļĄāļēāđāļāļēāļ°āļĨึāļ āļāļēāļĢāļāļģ Dark Mode āđāļ Next.js āđāļāļāļāļĢāļāļุāļāļ§ิāļี āļั้āļāđāļ้ CSS Variables, useState, localStorage āđāļĨāļ°āđāļĨāļāļĢāļēāļĢีāđāļŠāļĢิāļĄ āđāļ่āļ Next Themes āļัāļ Tailwind CSS āļāļĢ้āļāļĄāļัāļ§āļāļĒ่āļēāļāđāļ้āļāļี่āđāļāļēāđāļāđāļ้āđāļ้āđāļĨāļĒ! ð
ðĨ āļāļģāđāļĄāļ้āļāļāļĄี Dark Mode?
✅ āļ้āļāļีāļāļāļ Dark Mode
- āļ่āļ§āļĒāļĨāļāļāļēāļāļēāļĢāļĨ้āļēāļŠāļēāļĒāļāļē ð (āļŠāļģāļŦāļĢัāļāļāļāļี่āđāļ้āđāļ§็āļāļāļāļāļāļĨāļēāļāļืāļ)
- āļāļĢāļ°āļŦāļĒัāļāđāļāļāđāļāļāļĢี่ ð (āđāļāļĒāđāļāļāļēāļ°āļāļ OLED)
- āļูāđāļ่! ð āļŦāļĨāļēāļĒāđāļ§็āļāđāļŦāļ่āđ āļ็āđāļ้ āđāļ่āļ YouTube, Twitter
ð āļ§ิāļีāļāļģ Dark Mode āđāļ Next.js
ð 1. āđāļ้ CSS Variables + useState
āļ§ิāļีāļี้āđāļŦāļĄāļēāļ°āļัāļ:
✅ āđāļ§็āļāļี่āđāļĄ่āļัāļāļ้āļāļāļĄāļēāļ
✅ āđāļĄ่āļ้āļāļāđāļ้āđāļĨāļāļĢāļēāļĢีāđāļŠāļĢิāļĄ
ðĻðŧ āļั้āļāļāļāļāļāļēāļĢāļāļģ
1️⃣ āļŠāļĢ้āļēāļ globals.css āđāļĨāļ°āļāļģāļŦāļāļ Theme
āđāļ้āđāļāđāļāļĨ์ styles/globals.css
:root {
--bg-color: #ffffff;
--text-color: #000000;
}
.dark-mode {
--bg-color: #121212;
--text-color: #ffffff;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
transition: background 0.3s, color 0.3s;
}
2️⃣ āđāļิ่āļĄāļุ่āļĄāļŠāļĨัāļāđāļŦāļĄāļāđāļ index.js
āđāļิāļāđāļāļĨ์ pages/index.js āđāļĨ้āļ§āđāļิ่āļĄāđāļ้āļāļี้
import { useState } from "react";
export default function Home() {
const [darkMode, setDarkMode] = useState(false);
const toggleDarkMode = () => {
setDarkMode(!darkMode);
document.body.classList.toggle("dark-mode");
};
return (
<div style={{ textAlign: "center", marginTop: "50px" }}>
<h1>Dark Mode in Next.js ð</h1>
<button
onClick={toggleDarkMode}
style={{
padding: "10px 20px",
fontSize: "18px",
cursor: "pointer",
background: darkMode ? "#fff" : "#333",
color: darkMode ? "#000" : "#fff",
border: "none",
borderRadius: "5px",
}}
>
{darkMode ? "Switch to Light Mode ☀️" : "Switch to Dark Mode ð"}
</button>
</div>
);
}
ð 2. āđāļ้ localStorage āļāļģāļ่āļēāđāļŦāļĄāļ
āļัāļāļŦāļē: āļ้āļēāļĢีāđāļāļĢāļāļŦāļ้āļēāđāļ§็āļ āļ่āļēāđāļŦāļĄāļāļี่āđāļĨืāļāļāđāļ§้āļāļ°āļŦāļēāļĒāđāļ
āļāļēāļāđāļ้: āđāļ้ localStorage āļāļģāļ่āļēāļāļēāļĢāļั้āļāļ่āļēāļāļāļāļู้āđāļ้
āļัāļāđāļāļāđāļ้āļ index.js
import { useState, useEffect } from "react";
export default function Home() {
const [darkMode, setDarkMode] = useState(false);
useEffect(() => {
const savedTheme = localStorage.getItem("theme");
if (savedTheme === "dark") {
setDarkMode(true);
document.body.classList.add("dark-mode");
}
}, []);
const toggleDarkMode = () => {
setDarkMode(!darkMode);
if (!darkMode) {
document.body.classList.add("dark-mode");
localStorage.setItem("theme", "dark");
} else {
document.body.classList.remove("dark-mode");
localStorage.setItem("theme", "light");
}
};
return (
<div style={{ textAlign: "center", marginTop: "50px" }}>
<h1>Dark Mode in Next.js ð</h1>
<button
onClick={toggleDarkMode}
style={{
padding: "10px 20px",
fontSize: "18px",
cursor: "pointer",
background: darkMode ? "#fff" : "#333",
color: darkMode ? "#000" : "#fff",
border: "none",
borderRadius: "5px",
}}
>
{darkMode ? "Switch to Light Mode ☀️" : "Switch to Dark Mode ð"}
</button>
</div>
);
}
✅ āļ้āļāļี:
- āļāļģāļ่āļēāļีāļĄāđāļ้āļŦāļĨัāļāļāļēāļāļĢีāđāļāļĢāļ
ðĻ 3. āđāļ้ next-themes (āđāļāļ°āļāļģ!)
✅ āļ้āļāļีāļāļāļ next-themes
- āđāļ้āļ่āļēāļĒāļĄāļēāļ (āđāļĄ่āļ้āļāļāđāļีāļĒāļāđāļ้āļāđāļĒāļāļ°)
- āļĢāļāļāļĢัāļ āļĢāļ°āļāļ Dark Mode āļัāļāđāļāļĄัāļิāļāļēāļ OS
ð āļิāļāļั้āļ next-themes
npm install next-themes
ðĻðŧ āđāļ้āļāļēāļ next-themes
1️⃣ āđāļ้āđāļ _app.js
import { ThemeProvider } from "next-themes";
export default function MyApp({ Component, pageProps }) {
return (
<ThemeProvider attribute="class">
<Component {...pageProps} />
</ThemeProvider>
);
}
2️⃣ āđāļ้āđāļ index.js
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
export default function Home() {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return null; // āļ้āļāļāļัāļ Hydration Error
return (
<div className="p-5 text-center">
<h1 className="text-2xl">Dark Mode with next-themes ð</h1>
<button
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
className="mt-3 px-4 py-2 text-white bg-black rounded"
>
{theme === "dark" ? "Switch to Light Mode ☀️" : "Switch to Dark Mode ð"}
</button>
</div>
);
}
ðĨ āļ่āļēāļĒāļŠุāļāđ āđāļ่āđāļĢีāļĒāļ setTheme() āđāļĨ้āļ§āļāļĨ่āļāļĒāđāļŦ้ next-themes āļัāļāļāļēāļĢāđāļŦ้!
ð āļŠāļĢุāļ
| āļ§ิāļี | āļ้āļāļี | āļ้āļāđāļŠีāļĒ |
|---|---|---|
| CSS Variables + useState | āļ่āļēāļĒ, āđāļĄ่āļ้āļāļāđāļ้āđāļĨāļāļĢāļēāļĢี | āļĢีāđāļāļĢāļāđāļĨ้āļ§āļ่āļēāļŦāļēāļĒ |
| localStorage | āļāļģāļ่āļēāļีāļĄāđāļ้āļŦāļĨัāļāļĢีāđāļāļĢāļ | āļ้āļāļāđāļ้ useEffect |
| next-themes (āđāļāļ°āļāļģ) | āļĢāļāļāļĢัāļ Dark Mode āļัāļāđāļāļĄัāļิ | āļ้āļāļāļิāļāļั้āļāđāļĨāļāļĢāļēāļĢี |
ðŊ āļ้āļēāļุāļāļāļĒāļēāļāļāļģ Dark Mode āđāļāļāļ่āļēāļĒāļŠุāļ ð āđāļ้ next-themes
ðŊ āļ้āļēāļāļĒāļēāļāļāļ§āļāļุāļĄāđāļāļāļั้āļāļŦāļĄāļ ð āđāļ้ CSS Variables + localStorage
ð āļĨāļāļāļāļģāđāļĨāļĒ āđāļĨ้āļ§āđāļ§็āļāļāļāļāļุāļāļāļ°āļูāđāļāļĢāļึ้āļ 300%!! ð
āđāļĄ่āļĄีāļāļ§āļēāļĄāļิāļāđāļŦ็āļ:
āđāļŠāļāļāļāļ§āļēāļĄāļิāļāđāļŦ็āļ