Add Dark mode in Nextjs App using Tailwind CSS Dark Mode.
Tags: nextjs, tailwindcss
Published: 2022-03-06 04:50:53

---
title: Add Dark mode in Nextjs App using Tailwind CSS Dark Mode.
published: true
date: 2022-02-20 07:04:00 UTC
tags: Nextjs,TailwindCSS
canonical_url: https://nextjsdev.com/add-dark-mode-in-nextjs-app-using-tailwind-css-dark-mode/
---

 ![Add Dark mode in Nextjs App using Tailwind CSS Dark Mode.](https://nextjsdev.com/content/images/2022/02/nextjs-image-4.PNG)

Hello everyone, I hope you are good and doing well. Today, we are going to discuss how we can add dark mode in Next.js App using Tailwind CSS dark mode in just 5 easy steps. So, Let's begin.

Having a bright screen at night is painful for our eyes. That's why the dark mode feature is necessary if we want to take care of our user's eyes.  
In this lesson, we'll learn how to enable dark mode in our Next.js application to keep our users engaged with our app all night long.

We will see how we can easily implement the dark mode feature by using and combining next-themes and Tailwind CSS.

And we'll add the ability for our users to toggle between light and dark mode from the user interface.

Here is the image of the website:

 ![Add Dark mode in Nextjs App using Tailwind CSS Dark Mode.](https://nextjsdev.com/content/images/2022/02/nextjs-light-mode.PNG)

 ![Add Dark mode in Nextjs App using Tailwind CSS Dark Mode.](https://nextjsdev.com/content/images/2022/02/Nextjs-dark-mode.PNG)

**Tech Stack used:**

1. Next.js
2. Tailwind CSS
3. React.js

**Npm Packages used:**

1. next-themes
2. @heroicons/react

Here is a little demo of the project, that we are going to build and the GitHub link of the project also.

> [Demo Link of the Project](https://nextjs-app-dark-mode.vercel.app/)

> [Github Link of the Project](https://github.com/raiv200/Nextjs-Dark-Mode)

## Step-1 Create Nextjs App and add Tailwind CSS.

First of all, create a Next.js project and add Tailwind CSS in it or you can create a new Next.js App with Tailwind CSS added in it already using this command.

<!--kg-card-begin: markdown-->
```
npx create-next-app my-project // without Tailwind CSS installed
or
npx create-next-app -e with-tailwindcss my-project //with Tailwind CSS

```
<!--kg-card-end: markdown-->

Now you have to install two packages **next-themes** and   **@heroicons/react** from npm.

<!--kg-card-begin: markdown-->
```bash
npm install next-themes @heroicons/react

```
<!--kg-card-end: markdown-->
## Step-2 Creating Navbar and Hero Section.

Let's create a simple Navbar, with a Hero section so that we can look at the changes of dark mode and light mode themes.

So,  first of all, create two folders named **components** and **sections** in the root of the directory.

Inside the **components** , create a file name Logo.js and paste this code inside that.

**Inside Logo.js write this code:**

<!--kg-card-begin: markdown-->
```jsx
import { LightningBoltIcon } from "@heroicons/react/solid";
import Link from "next/link";

const Logo = () => {
    return (
        <Link href="/">
        <a className="my-2 flex items-center space-x-1 text-indigo-500">
          <LightningBoltIcon className="h-8 w-8 flex-shrink-0 mr-3"/>
          <span className="font-bold text-3xl font-sans tracking-tight whitespace-nowrap">Next-js Dev</span>
        </a>      
        </Link>
    )
}

export default Logo;
```
<!--kg-card-end: markdown-->

Then create three files inside the section folder.

1. **Header.js**
2. **Layout.js**
3. **Footer.js**

The file structure will look like this:

![Add Dark mode in Nextjs App using Tailwind CSS Dark Mode.](https://nextjsdev.com/content/images/2022/02/file-structure-dark-mode.PNG)
_File structure of the Nextjs App_

**Inside the Header.js write this code:**

<!--kg-card-begin: markdown-->
```jsx
import Logo from "../components/Logo";

const Header = () => {

  return (
    <header className="h-15 shadow-sm dark:border-gray-700">
      <div className="container px-4 sm:px-6 py-4 flex justify-between items-center">
        {/* Logo */}
        <Logo />
      </div>
    </header>
  );
};

export default Header;

```
<!--kg-card-end: markdown-->

**Inside the Footer.js write this code:**

<!--kg-card-begin: markdown-->
```jsx
const Footer = () => {
  return (
    <footer className="px-4 sm:px-6 py-6 mt-24">
      <div className="text-center text-sm text-gray-500">
        <span className="dark:text-gray-100 text-gray-900 font-bold text-lg mr-2"> Next.js Dev</span> &copy; {new Date().getFullYear()} All Rights Reserved
      </div>
    </footer>
  );
};

export default Footer;

```
<!--kg-card-end: markdown-->

**Inside the Layout.js write this code:**

<!--kg-card-begin: markdown-->
```jsx
import Header from "./Header";
import Footer from "./Footer";
import Head from "next/head";

const Layout = ({ children}) => {
  return (
    <>
      <Head>
        <title>Nextjs-Dev Blog</title>
        <link rel="icon" href="/favicon.ico" />
        
      </Head>

      <div className="min-h-screen mx-auto max-w-2xl flex flex-col">
        <Header />
        <main className="flex-grow container mx-auto px-4 sm:px-6">
          {children}
        </main>
        <Footer />
      </div>
    </>
  );
};

export default Layout;

```
<!--kg-card-end: markdown-->
## Step-3 Importing the ThemeProvider from next-themes.

Now, open the \_app.js inside the pages folder and write the following code given below.

**Inside \_app.js file:**

<!--kg-card-begin: markdown-->
```jsx
import "tailwindcss/tailwind.css";
import "../styles/globals.css";
import { ThemeProvider } from "next-themes";

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider enableSystem={true} attribute="class">
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

export default MyApp;

```
<!--kg-card-end: markdown-->

After that open the tailwind.config.js file and then add a property **darkMode** in it and give a value "class" to it like this.

<!--kg-card-begin: markdown-->
```js
module.exports = {
  mode: "jit",
  purge: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
    "./sections/**/*.{js,ts,jsx,tsx}",
  ],
  darkMode: "class", 
  theme: {
    extend: {
    },
  },
  variants: {
    extend: {},
  },
  plugins: [],
};

```
<!--kg-card-end: markdown-->

Now, whenever, the `dark` class is present earlier in the HTML tree, tailwind CSS will apply the dark styles, otherwise, it applies the light theme by default.

## Step-4  Adding a toggle button to control dark mode manually.

Now let's add the ability to toggle the dark mode manually from the user interface.

Open the `Header.js` file from the `sections` folder, and import the ` **useTheme** ` hook from `next-themes`, along with the ` **MoonIcon** ` and the ` **SunIcon** ` components from heroicons.

Then, retrieve the ` **systemTheme** `, the ` **theme** `, and the ` **setTheme** ` properties by calling `useTheme` at the top of your component.

From there, create a new method names ` **renderThemeChanger** ` and get the current theme from the system or the `theme` variable.

Now, if the current theme is dark, we return the `SunIcon` component and implement the `onClick` event by using the `setTheme` method from `next-themes` to toggle the theme back to light on click to this icon.

Otherwise, we return the `MoonIcon` component and set the theme to dark on click.

Finally, we can call this new method right inside our JSX to render the current theme icon, and align it with our logo with flexbox.

**The Header.js file now looks like this:**

<!--kg-card-begin: markdown-->
```jsx
import Logo from "../components/Logo";
import {useTheme} from "next-themes";
import{SunIcon ,MoonIcon} from "@heroicons/react/solid";

const Header = () => {

  const {systemTheme , theme, setTheme} = useTheme ();

  const renderThemeChanger= () => {

      const currentTheme = theme === "system" ? systemTheme : theme ;

      if(currentTheme ==="dark"){
        return (
          <SunIcon className="w-10 h-10 text-yellow-500 " role="button" onClick={() => setTheme('light')} />
        )
      }

      else {
        return (
          <MoonIcon className="w-10 h-10 text-gray-900 " role="button" onClick={() => setTheme('dark')} />
        )
      }
   };

  return (
    <header className="h-15 shadow-sm dark:border-gray-700">
      <div className="container px-4 sm:px-6 py-4 flex justify-between items-center">
        {/* Logo */}
        <Logo />

        {renderThemeChanger()}
      </div>
    </header>
  );
};

export default Header;

```
<!--kg-card-end: markdown-->
## Step-5  To avoid hydration mismatch.

There is one more thing we need to do to avoid hydration mismatch.

Because we cannot know the theme on the server, the values returned from `useTheme` will be `undefined` until mounted on the client.

In other words, our theme icon will not match the actual current theme. And that's pretty bad for user experience.

So to fix this, we need to make sure we only render our icon when the page is mounted on the client.

So, import the `useState` and `useEffect` hooks from `react`.And create a new state variable to track if the component has been mounted or not on the client-side.

Set the initial value to false, and then set its value to true inside a `useEffect` hook.

Finally, inside the `renderThemeChanger`, check if the component is mounted before rendering the UI for the theme changer.

**Inside Header.js file:**

<!--kg-card-begin: markdown-->
```jsx
import {useState, useEffect} from "react";

const Header = () => {
const [mounted, setMounted] = useState(false);
  
  useEffect(() =>{
    setMounted(true);
  },[])

const renderThemeChanger= () => {
      if(!mounted) return null;

      const currentTheme = theme === "system" ? systemTheme : theme ;

      if(currentTheme ==="dark"){
        return (
          <SunIcon className="w-10 h-10 text-yellow-500 " role="button" onClick={() => setTheme('light')} />
        )
      }

      else {
        return (
          <MoonIcon className="w-10 h-10 text-gray-900 " role="button" onClick={() => setTheme('dark')} />
        )
      }
   };
}

```
<!--kg-card-end: markdown-->
## Step-6  Time to add Dark Mode variant styles.

Now that everything is all set, let's add the styles to our elements using the `dark` variant from Tailwind CSS, save your file and refresh your browser.

Now navigate to the **styles** folder and open the global.css file.

Inside **global.css** that paste this code:

<!--kg-card-begin: markdown-->
```css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  body {
    @apply bg-gray-50 text-gray-900 dark:bg-black dark:text-gray-100;
    @apply min-h-screen;
  }

  ::selection {
    @apply text-white bg-indigo-500;
  }

  
  .btn{
    @apply inline-block px-5 py-3 rounded-lg hover:bg-indigo-600 transition duration-300 shadow-lg bg-indigo-500 text-white capitalize tracking-wider font-semibold text-sm sm:text-xl focus:outline-none focus:ring-4 focus:ring-indigo-500 focus:ring-opacity-50 whitespace-nowrap
  }
}

```
<!--kg-card-end: markdown-->

You can now change the theme of your application manually from  
the UI which is what we wanted.

You can easily change those dark variants by just adding classes like this:

<!--kg-card-begin: markdown-->
```html
<h1 className=" dark:bg-gray-900 dark:text-gray-100 " >This is H1 heading</h1>

```
<!--kg-card-end: markdown-->
## Conclusion

So that was all about adding Dark mode in Nextjs App using Tailwind CSS. I hope you like this and enjoyed building this project.

If you think that this was helpful and then please do consider visiting my original blog link and do follow me on **Twitter** and connect with me on **LinkedIn**.

If you were stuck somewhere and not able to find the solution you can check out my completed [github repository](https://github.com/raiv200/Nextjs-Dark-Mode) here.

Thanks for your time to read this project, if you like this please share it on Twitter and Facebook or any other social media and tag me there.

Some Useful Link:

1. [Next.js and Tailwind Installation Docs](https://tailwindcss.com/docs/guides/nextjs)
2. [Github link for project](https://github.com/raiv200/Nextjs-Dark-Mode)

Connect with me:

1. [Twitter Link](https://twitter.com/raivikas200)
2. [LinkedIn link](https://www.linkedin.com/in/raivikas200/)
3. [Facebook Link](https://www.facebook.com/raiv200/)
4. [Github Link](https://github.com/raiv200)