DEV Community

Cover image for Dark mode using Tailwindcss v4.0
TenE
TenE

Posted on • Edited on

4

Dark mode using Tailwindcss v4.0

Dark Mode Toggle in React

Dark mode is a theme selector that enhances user engagement by respecting their preferred theme.

Overview

In this blog, we will cover how to toggle between two themes: light and dark. (Multi-theme selection will be covered in upcoming blogs.)

UI Component

We will create a reusable UI component, a button that can be placed anywhere in the application while maintaining the same functionality.

Toggle Button UI

<div
  className="relative w-14 h-8 rounded-3xl bg-slate-300 dark:bg-zinc-700 place-center cursor-pointer"
>
  <div
    className="absolute top-1 rounded-full w-6 h-6 bg-blue-500"
  />
</div>
Enter fullscreen mode Exit fullscreen mode

In global.css or index.css

The following styles help integrate Tailwind CSS and define a custom variant for dark mode:

@import 'tailwindcss';

/* Define a custom variant for dark mode */
@custom-variant dark (&:is(.dark *));
Enter fullscreen mode Exit fullscreen mode
  • @import 'tailwindcss'; Loads Tailwind CSS into your global styles.
  • @custom-variant dark (&:is(.dark *));
    • Creates a custom Tailwind variant named dark.
    • Uses :is(.dark *) to apply styles when any parent element has the .dark class.
    • Ensures that child elements automatically inherit dark mode styles.

Creating a Custom Hook for Toggling Dark Mode

We will now create a custom hook, useDarkMode, to handle dark mode toggling.

Custom Hook: useDarkMode

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

export default function useDarkMode() {
  const [isDarkMode, setIsDarkMode] = useState<boolean>(() => {
    const savedTheme = localStorage.getItem("theme");
    if (savedTheme) {
      return savedTheme === "dark";
    }
    return window.matchMedia("(prefers-color-scheme: dark)").matches;
  });

  // Toggle dark mode
  const toggleDarkMode = useCallback(() => {
    setIsDarkMode((prev) => {
      const newMode = !prev;
      const html = document.documentElement;
      if (newMode) {
        html.classList.add("dark");
        localStorage.setItem("theme", "dark");
      } else {
        html.classList.remove("dark");
        localStorage.setItem("theme", "light");
      }
      return newMode;
    });
  }, []);

  // Sync the theme with the <html> element
  useEffect(() => {
    const html = document.documentElement;
    if (isDarkMode) {
      html.classList.add("dark");
    } else {
      html.classList.remove("dark");
    }
  }, [isDarkMode]);

  return { isDarkMode, toggleDarkMode };
}
Enter fullscreen mode Exit fullscreen mode

Explanation of useDarkMode

  • State Initialization: It first checks localStorage for a saved theme preference. If none exists, it defaults to the system theme preference.
  • Toggling Theme: The toggleDarkMode function switches the theme, updates the html class, and stores the new theme in localStorage.
  • Effect Hook: Ensures the theme remains synced with the html element when the component renders.

Using the Hook in a Component

Now, we will use useDarkMode in a component to toggle dark mode.

ToggleDarkMode Component

import useDarkMode from "../../../hooks/useDarkMode";

export default function ToggleDarkMode() {
  const { toggleDarkMode, isDarkMode } = useDarkMode();

  return (
    <div
      onClick={toggleDarkMode}
      className="relative w-14 h-8 rounded-3xl bg-slate-300 dark:bg-zinc-700 place--center cursor-pointer"
    >
      <div
        className={`absolute top-1 rounded-full w-6 h-6 bg-blue-500 ${isDarkMode ? "left-1" : "right-1"}`}
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Explanation

  • Imports useDarkMode Hook: Extracts toggleDarkMode and isDarkMode from the hook.
  • UI Structure: A switch-like button that changes its position based on isDarkMode.
  • Click Handler: Calls toggleDarkMode to switch themes.

Using in Your App

Now you can import and use <ToggleDarkMode /> anywhere in your application!

Example: Using It in a Navbar

import ToggleDarkMode from "./components/ToggleDarkMode";

export default function Navbar() {
  return (
    <nav className="flex justify-between items-center p-4 bg-white dark:bg-black">
      <h1 className="text-xl font-bold text-gray-900 dark:text-white">My Website</h1>
      <ToggleDarkMode />
    </nav>
  );
}
Enter fullscreen mode Exit fullscreen mode

Demo

Check out the live demo: Dark Mode Toggle

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (2)

Collapse
 
sreeharshrajan profile image
Sreeharsh K

Hi It didnt work

Collapse
 
tene profile image
TenE

Hey! Could you share more details on the issue? Is there a console error, or is the toggle not working as expected? Also, ensure Tailwind CSS v4.0 is set up correctly. Happy to help!

👋 Kindness is contagious

Dive into this insightful write-up, celebrated within the collaborative DEV Community. Developers at any stage are invited to contribute and elevate our shared skills.

A simple "thank you" can boost someone’s spirits—leave your kudos in the comments!

On DEV, exchanging ideas fuels progress and deepens our connections. If this post helped you, a brief note of thanks goes a long way.

Okay