shahriyar.dev
Back to blog
Tailwind CSSReact HookDark Mode TogglelocalStorageUser PreferenceClass-based Dark Mode

Implement a Manual Dark Mode Toggle in Your Tailwind CSS Site with a Custom React Hook

·3 min read

Adding a manual dark mode toggle to your Tailwind CSS website enhances user experience by giving visitors control over their viewing preferences. This approach is simple to implement and relies on toggling a class on the HTML element. Below, I'll walk through the steps to set it up using a custom React hook.

Configuring Tailwind for Manual Dark Mode

The first step is to update your Tailwind configuration to support class-based dark mode. By default, Tailwind uses the prefers-color-scheme media query, but switching to a class-based approach allows manual control.

In your tailwind.config.js file, add the darkMode option set to "class":

js
module.exports = {
  darkMode: "class",
  // ... other config options
}

This tells Tailwind to apply dark mode styles whenever a parent element (like <html>) has the dark class.

Creating a Custom Theme Hook

To manage the theme state and toggle functionality efficiently, create a custom React hook. This hook will handle reading the current theme from localStorage (if set), updating the HTML class, and providing a toggle function.

Here's the useTheme hook:

js
import { useEffect, useState } from "react";

export const useTheme = () => {
  const [mode, setMode] = useState("light");

  function changeTheme() {
    const html = document.documentElement;

    if (mode === "light") {
      html.classList.remove("light");
      html.classList.add("dark");
      setMode("dark");
      localStorage.setItem("mode", "dark");
    } else {
      html.classList.remove("dark");
      html.classList.add("light");
      setMode("light");
      localStorage.setItem("mode", "light");
    }
  }

  useEffect(() => {
    const currentMode = localStorage.getItem("mode") || "light";
    document.documentElement.classList.add(currentMode);
    setMode(currentMode);
  }, []);

  return { changeTheme, mode };
};

Key points about this hook:

  • It initializes the theme from localStorage (defaulting to "light" if none is stored)
  • The changeTheme function toggles between light and dark modes by swapping classes on the <html> element and updating state
  • It persists the user's preference via localStorage, so the theme remembers their choice across sessions
  • The hook returns both the changeTheme function and the current mode, giving you flexible integration options

Using the Hook in Components

Once the hook is ready, you can import it into any component where you want a theme toggle button. For example, a simple theme switcher button might look like this:

js
function ThemeButton() {
  const { changeTheme } = useTheme();

  return (
    <button onClick={changeTheme}>Toggle Dark Mode</button>
  );
}

Clicking the button calls changeTheme, which flips between light and dark modes. The UI updates instantly thanks to Tailwind's class-based approach, and the preference is saved for future visits.

Additional Resources

By following these steps, you can give your website visitors a seamless and personalized experience with manual dark mode control. The implementation is lightweight, respects user preferences, and integrates smoothly with any React-based Tailwind project.

Comments