Last updated: July 25, 2022

How to Implement Dark Mode Feature in NextJs and TailwindCSS project.

As developers, we spend a lot of time on our favorite IDE to write code, algorithms, and develop applications. This becomes an acceptable standard for our eyes and we start to avoid the sharp blue/ white light on our screens.

Similarly, to allow your readers an option to switch between dark and light mode, we can implement a dark mode feature in our website.

This can be done by adding the following code snippet into a custom React Hook.

import { useEffect, useState } from 'react';

export default function useDarkMode() {
  const [darkMode, setDarkMode] = useState(false);

  useEffect(() => {
    const root = window.document.documentElement;
    if (darkMode) {
      root.classList.add('dark');
    }
    if (!darkMode) {
      root.classList.remove('dark');
    }
  }, [darkMode]);

  return [darkMode, setDarkMode];
}

In the above code snippet, we initialized a state for our dark mode and set its default value to false.

Second, we used React useEffect hook to add this dark class to our HTML head element.

The above code is enough to enable or disable the dark mode in our website. However, if the user leaves our site or refreshes the page, we''ll lose our state and the dark class will get removed from our HTML document.

Fortunately, we have a solution for this and we can save this state in the local storage of user's web browser. If the user returns to our site later, we will be able to return the last saved mode.

Our final code will look like the code snippet below. Some web applications like Stripe use cookies to store this theme state. This can be achieved by using a server side logic and it is a bit more complicated than the above example. For now, let's use the local storage for implementing our dark mode feature.

export default function useDarkMode() {
  const [darkMode, setDarkMode] = useState(false);

  useEffect(() => {
    const checkTheme = localStorage.getItem('theme');
    if (checkTheme) {
      checkTheme === 'dark' ? setDarkMode(true) : null;
    }
  }, []);

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

  return [darkMode, setDarkMode];
}

Here, we use another useEffect hook that will run whenever our website is accessed. We created a function inside this hook to access the local storage of user's web browser.

The dark mode state is updated if the key with name 'theme' is available. If it is not available, we save the key in local storage if our user wants to switch to the dark mode.

Finally, all we need to do is import our custom hook in the component where we want to add the dark mode switch. Before we do that, configure the tailwind.config.js file and add the key darkMode with value class.

module.exports = {
  darkMode: 'class',
  //...
}

On this website, we are using the dark mode switch in the navigation bar at the top right. Let's import our custom hook inside the NavBar component and create a switch to enable or disable the dark mode.

import useDarkMode from './useDarkMode';

export default function NavBar () {
  const [darkMode, setDarkMode] = useDarkMode();

  return (
    <>
      <header className='dark:bg-[#1a1a1a] bg-white dark:text-white text-black sticky top-0 z-10 w-full py-1'>
        <nav className='max-w-7xl mx-auto w-full py-2 flex justify-between px-4'>
          //...

          <div className='flex items-center'>
            {darkMode ? (
              <button onClick={() => setDarkMode(false)}>
                // Your icon here...
              </button>
            ) : (
            <button onClick={() => setDarkMode(true)}
              className='w-6 h-6 border-2 border-[#1a1a1a] rounded-full flex justify-center items-center'
            >
              // Your icon here...
            </button>
          )}
          </div>
        </nav>
      </header>
    </>
  );
};




We have created a custom React hook that allows us to use dark mode switch in our website. Feel free to replace the SVG in the above with your own if you like.

To get more updates for my code snippets, follow me on twitter. Thanks for fetching this post. Buy me a coffee if you like it!