Besharamcode

Creating a Dark Mode Toggle in React with Tailwind CSS v4

about 2 months ago

Mohit Kushwah

Dark mode has become a must-have feature in modern web apps. With Tailwind CSS v4, enabling dark mode is simpler, cleaner—and different from earlier versions. In this guide, we’ll build a beautiful and functional Dark Mode Toggle in a React app using Tailwind v4 and Vite.

Step 1: Setting Up the Project

We’re using Vite for a fast development setup, with React and Tailwind CSS v4.

Install Dependencies

Run the following to set up Tailwind and its Vite plugin:

npm install tailwindcss @tailwindcss/vite

Configure Vite

In vite.config.js, import the Tailwind Vite plugin:

// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [react(), tailwindcss()],
});

Step 2: Enable Dark Mode in Tailwind v4

Tailwind v4 has removed the darkMode: 'class' option. Instead, we enable it via custom variants in the global CSS file.

Create or Edit index.css

@import "tailwindcss";

@custom-variant dark (&:where(.dark, .dark *));

This tells Tailwind to apply dark mode styles whenever an element or any of its children has the dark class.

Step 3: Create the Dark Mode Toggle Component

This component handles toggling and storing the user's dark mode preference.

// DarkToggle.jsx
import { useEffect, useState } from "react";

const DarkModeToggle = () => {
  const [darkMode, setDarkMode] = useState(() => {
    return localStorage.getItem("theme") === "dark";
  });

  useEffect(() => {
    const root = document.documentElement;
    if (darkMode) {
      root.classList.add("dark");
      localStorage.setItem("theme", "dark");
    } else {
      root.classList.remove("dark");
      localStorage.setItem("theme", "light");
    }
  }, [darkMode]);

  return (
    <button
      onClick={() => setDarkMode((prev) => !prev)}
      className="px-4 py-2 rounded-md bg-gray-200 dark:bg-gray-800 text-black dark:text-white shadow"
    >
      {darkMode ? "☀️ Light Mode" : "🌙 Dark Mode"}
    </button>
  );
};

export default DarkModeToggle;

Step 4: Use the Toggle in Your App

Now, plug the toggle button into your main app layout.

// App.jsx
import DarkModeToggle from "./DarkToggle";

export default function App() {
  return (
    <div className="min-h-screen flex flex-col items-center justify-center bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-300">
      <h1 className="text-3xl font-bold mb-6">Tailwind v4 Dark Mode</h1>
      <DarkModeToggle />
    </div>
  );
}

Final Touches

You can now style your entire app using dark: classes:

<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
  {/* content */}
</div>

Add transition effects for smoother theme switching:

transition-colors duration-300

Conclusion

With just a few lines of code, you've added a dark mode toggle that:

  • members the user's preference in localStorage
  • es Tailwind v4’s new @custom-variant system
  • plies styles cleanly with dark: variants

Tailwind CSS v4 may feel different at first, but it offers greater flexibility. Now go ahead and make your UI shine (or dim 😄)!

Bonus Tips

  • e icons like 🌙 and ☀️ for a better user experience.
  • d animations with Tailwind’s transition and duration utilities.
  • u can extend dark mode to more components with ease using Tailwind’s dark: variant.

View the full repository and implementation here: https://github.com/besharamcode/toggle-theme-using-tailwind-css

The image is a screenshot of a blog post or tutorial titled "Creating a Dark Mode Toggle in React with Tailwind CSS." The text is set against a dark background, suggesting a dark mode theme itself.

NOTE: This blog post was created with the assistance of AI tools to help structure content, clarify concepts, and speed up writing. However, all topics, code snippets, insights, and testing have been personally reviewed and refined by me to ensure accuracy and developer relevance. The goal is to share practical knowledge with fellow developers—faster and smarter.

Leave a Comment

Comments: