Dark Mode in Next.js Made Easy with TailwindCSS and Next Theme

Lee Robinson

Paul Berthelot / April 04, 2023

3 min read–––

In this post, I want to share with you my thoughts on the best way to set up dark mode in Next.js using TailwindCSS and next-theme.

As developers, we know that dark mode is not just a trend but a critical feature for modern web applications. It not only reduces eye strain but also creates a visually appealing and immersive experience for users. That's why I believe that setting up dark mode in your Next.js app can be a must.

In this tutorial, I'll walk you through the entire process of setting up dark mode in Next.js with TailwindCSS and Next Theme. We'll start by installing the necessary packages and configuring the theme object. Then, we'll create two buttons to switch between light and dark mode, and update the styles accordingly.

By the end of this tutorial, you'll have a fully functional dark mode feature in your Next.js application, and you'll be equipped with the knowledge and tools to create a seamless user experience for your users.

So, let's get started!

next-theme is a package that provides a simple way to implement theming functionality in your Next.js application. Here are the basic steps to use next-theme in your project:

  1. Install the next-theme package using npm:
npm install next-themes
  1. Import the ThemeProvider component from next-theme in your \_app.tsx file. If you don't have an \_app.tsx file, create one in your pages directory.
/pages/_app.tsx
import '@assets/main.css'
import { ThemeProvider } from 'next-themes'

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp

That's it, your Next.js app fully supports dark mode, including System preference with prefers-color-scheme. The theme is also immediately synced between tabs. By default, next-themes modifies the data-theme attribute on the html element, which you can easily use to style your app.

main.css
@tailwind base;
@import './base.css';

@tailwind components;
@tailwind utilities;
base.css
:root {
  --primary: #ffffff;
  --secondary: #000000;
  --text-primary: #000000;
  --text-secondary: white;
}

[data-theme="dark"] {
  --primary: #000000;
  --secondary: #ffffff;
  --text-primary: white;
  --text-secondary: #000000;
}
tailwind.config.js
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      colors: {
        primary: 'var(--primary)',
        secondary: 'var(--secondary)',
      },
      textColor: {
        primary: 'var(--text-primary)',
        secondary: 'var(--text-secondary)',
      }
    },
  },
}

Now, let's try it!

index.tsx
import Head from 'next/head'
import { useTheme } from 'next-themes'

export default function Home() {
    const { theme, setTheme } = useTheme()
    return (
    <>
        <Head>
        <title>My Next.js App</title>
        <meta name="description" content="A simple Next.js app" />
        </Head>

        <main>
        <p className="text-primary">This text adapts its color depending on the dark or light mode</p>
        <button onClick={() => setTheme('light')}>Light Mode</button>
        <button onClick={() => setTheme('dark')}>Dark Mode</button>
        </main>
    </>
    )
}

Subscribe to the newsletter

Get emails from me about web development, tech trends, and advices for founders.

24 subscribers