How to add dark mode in NextJS with Tailwind CSS?

These days, most modern websites have both light and dark mode options. Users tend to like dark mode the most. So, it's a wise decision to add a dark mode feature to your website.

How to add dark mode in NextJS with Tailwind CSS?

In this blog, I'll try to show you the fastest and easiest way to add dark mode to your NextJS project. I'll be using Tailwind CSS for styling.

Setting up the project file

I'm making a guess that you are already familiar with NextJS and Tailwind CSS. So, I'll not be going into depth about them. I'll be using the NextJS Tailwind starter template.

npx create-next-app --example with-tailwindcss

Set a project name and open the directory. You need to install the node packages with npm install. After that, your project directory should look like this:

📦dark_mode
 ┣ 📂pages
 ┃ ┣ 📂api
 ┃ ┃ ┗ 📜hello.ts
 ┃ ┣ 📜index.tsx
 ┃ ┗ 📜_app.tsx
 ┣ 📂public
 ┃ ┣ 📜favicon.ico
 ┃ ┗ 📜vercel.svg
 ┣ 📂styles
 ┃ ┗ 📜globals.css
 ┣ 📜.gitignore
 ┣ 📜next-env.d.ts
 ┣ 📜next.config.js
 ┣ 📜package.json
 ┣ 📜postcss.config.js
 ┣ 📜prettier.config.js
 ┣ 📜README.md
 ┣ 📜tailwind.config.js
 ┗ 📜tsconfig.json

The example template, by default, comes with Typescript. To make this simple, I'm changing the index file type from index.ts to index.js and I'll continue writing in JavaScript.

Remove the boilerplate code from the index.js file and add the following code to check if everything is working fine:

export default function Home() {
  return <h1 className="text-3xl font-bold underline">Hello world!</h1>
}

Now enable the dark mode option on Tailwind CSS. There are two options to choose from: "media" & "class". For this project, I'll be using "class" option. Add darkMode: 'class' to tailwind.config.js file.

module.exports = {
  darkMode: 'class',
  content:
  [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}'
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Step 1: Install next-themes

Before we begin, let me give you a brief overview of next-themes. With next-themes, you can achieve dark mode with only two lines of code. Syncs the theme across tabs and windows. It has no flash on load (both SSR and SSG). It's packed with tons of good features. More information is available on the Github Page.

npm install next-themes
# or
yarn add next-themes

Step 2: Setting up next-themes:

Headover to _app.js file and add the following code:

// pages/_app.js

import { ThemeProvider } from 'next-themes'
import '../styles/globals.css'

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

export default MyApp

Explaination: The ThemeProvider is a wrapper component that will provide the theme to the rest of the application. I've enabled the system theme by setting enableSystem to true. The attribute is the attribute that will be used to set the theme. In this case, I'm using class.

Step 3: Creating a reuseable dark mode toogle button:

Create a new folder in the root directory of your project called components. Inside this folder, create a new file called DarkModeToggle.

📦components
 ┗ 📜DarkModeToggle.js

Export a const function called DarkModeToggle that returns a button element.

export const DarkModeToggle = () => {
  return (
    <>
      <button>

      </button>
    </>
  )
}

Step 3.1: Styling the button a bit:

import { useState, useEffect } from 'react'

export const DarkModeToggle = () => {

  const [toogle, setToogle] = useState(false)

  return (
    <>
      <button
        checked={toogle}
        onClick={() => setToogle(!toogle)}
        className="focus relative inline-flex h-8 w-14
        flex-shrink-0 cursor-pointer rounded-full
        bg-slate-100 shadow-inner transition duration-200
        ease-in-out hover:bg-slate-200/60 dark:bg-green-500
        dark:hover:bg-green-500/90"
      >
        <span
          aria-hidden="true"
          className={`${toogle ? 'translate-x-6' : 'translate-x-0'}
            mt-1 ml-1 h-6 w-6 transform rounded-full
            bg-white shadow-lg ring-0 transition duration-300
            ease-in-out dark:bg-white`}
        />
      </button>
    </>
  )
}

Step 3.2: Adding the dark mode toogle with next-themes:

import { useTheme } from 'next-themes'
import { useState, useEffect } from 'react'

export const DarkModeToggle = () => {
  const { systemTheme, theme, setTheme } = useTheme('light')

  const [toogle, setToogle] = useState(false)

  useEffect(() => {
    if (toogle) {
      setTheme('dark')
    } else {
      setTheme('light')
    }
  }, [toogle])

  return (
    <>
      <button
        checked={toogle}
        onClick={() => setToogle(!toogle)}
        className="focus relative inline-flex h-8 w-14 flex-shrink-0 cursor-pointer
         rounded-full bg-slate-100 shadow-inner transition
         duration-200 ease-in-out hover:bg-slate-200/60
         dark:bg-green-500 dark:hover:bg-green-500/90"
      >
        <span
          aria-hidden="true"
          className={`${toogle ? 'translate-x-6' : 'translate-x-0'}
            mt-1 ml-1 h-6 w-6 transform rounded-full
            bg-white shadow-lg ring-0 transition duration-300
            ease-in-out dark:bg-white`}
        />
      </button>
    </>
  )
}

We are done! Now, let's add the dark mode to the index.js file and check if everything is working fine.

import { DarkModeToggle } from './../components/DarkModeToggle'
import { useTheme } from 'next-themes'
export default function Home() {
  const { theme } = useTheme()
  return (
    <div className="grid h-screen place-items-center bg-white dark:bg-slate-900">
      <div className="flex flex-col items-center">
        <h1 className="mb-12 text-4xl font-bold capitalize">{theme}</h1>
        <DarkModeToggle />
      </div>
    </div>
  )
}
How to add dark mode in NextJS with Tailwind CSS?

It looks pretty good! So, we are finally done building the dark mode feature for NextJS and Tailwind CSS Project. Feel free to leave a comment if you have any questions or suggestions. I will be happy to help you.

Views:-

Language: Javascript, CSS

Topics: Dark Mode, NextJS, Tailwind CSS