Implementing Dark Mode in Next.js with Tailwind CSS
Tags: nextjs, tailwindcss, webdev, javascript
Published: 2023-02-22 12:03:41

Dark mode has become an increasingly popular feature in web applications. With Next.js and Tailwind CSS, adding dark mode to your application is a breeze. 

In this post, we'll walk through how to implement dark mode in a Next.js application using Tailwind CSS and the next-themes library.



![Result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj38r8spyet3lhinrqs5.gif)




## Setting up the Project

To get started, we need a Next.js application with Tailwind CSS configured. You can use the following command to create a new Next.js app with Tailwind CSS:

```bash
   npx create-next-app -e with-tailwindcss appname
```

This will create a new Next.js app with Tailwind CSS configured.

## Implementing Dark Mode

Next.js makes it easy to implement dark mode using the dark variant in Tailwind CSS. You can prepend `dark:` to properties to indicate that they are for dark mode. For example, you can use `dark:bg-gray-900` to change the background color to gray-900 when the theme is set to dark.

By default, Next.js uses the system preferences to set the theme. However, we also need to toggle between light and dark modes. To do this, we can set the `darkMode` strategy to `class` in the `tailwind.config.js` file:

```js
module.exports = {
  darkMode: 'class',
  // ...
}
```
With this configuration, Tailwind CSS will apply the theme when the dark class is present in the HTML tree.

## Using `next-themes`

We need to toggle between and store the current theme somehow so that when user comes back it doesn't reset to default. One way of doing this could be with local storage and doing DOM manipulation.

In this blog, we'll do something way simpler and use `next-themes` which handles all the toggling and storing of our preference.

To install the library, run:
```bash
npm i next-themes
```

In the `_app.js` file, wrap your component with the `ThemeProvider` from `next-themes`. Set the `attribute` prop to `class` to allow the library to apply the theme to the HTML element.

```tsx
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { ThemeProvider } from "next-themes"

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ThemeProvider attribute="class">
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp
```

## Accessibility Considerations

It's important to ensure that your application is accessible in both light and dark mode. When choosing text and background colors, make sure that they have sufficient contrast. You can test the accessibility of your application using a tool like the Accessibility Insights browser extension.


## Adding some Global Styles
We can add some global styles to `global.css`. Here we set the background of the body to white in light mode and dark gray in dark mode.
```css
@layer base{
    body {
        @apply dark:bg-gray-800 bg-white
    }
}
```

## Adding a Toggle Button

To allow users to toggle between light and dark modes, we need to add a toggle button to our application. 

We use the `useTheme` hook to know what the current theme is, change the current theme using the `setTheme` method, and the system theme.

Initially, we set the theme to the system theme. 

The `onclick` event on the button toggles between the themes. We add some individual class using the `dark:` variant for the button.
```tsx
"use client"
import React from 'react'
import { useTheme } from "next-themes";


const Button = () => {
    const { systemTheme, theme, setTheme } = useTheme();
    const currentTheme = theme === 'system' ? systemTheme : theme;

    return (
        <button
            onClick={() => theme == "dark"? setTheme('light'): setTheme("dark")}
            className='bg-gray-800 dark:bg-gray-50 hover:bg-gray-600 dark:hover:bg-gray-300 transition-all duration-100 text-white dark:text-gray-800 px-8 py-2 text-2xl md:text-4xl rounded-lg absolute bottom-32'>
            Toggle Mode
        </button>
    )
}

export default Button
```


## Adding Elements to Index.tsx
We add the toggle button to `index.tsx`.
```tsx

      <main className="flex items-center justify-center h-screen flex-col">
        <h2 className={`${roboto.className} text-4xl sm:text-6xl md:text-9xl text-center text-gray-800`}>LIGHT MODE</h2>
        <h2 className={`${roboto.className} text-4xl sm:text-6xl md:text-9xl text-center text-white `}>DARK MODE</h2>
        <Button/>
      </main>

```

Voila! Let there be light...
![cat meme](https://media.tenor.com/GtQKFfsJ7e0AAAAC/flash-light.gif)

Find the complete project [here](https://github.com/ChinmayMhatre/DarkMode-Blog).