Creating a Dark Theme in Next.js with Tailwind CSS | A Complete Tutorial

Views: 236Published: 7/21/2024
Creating a Dark Theme in Next.js with Tailwind CSS | A Complete Tutorial

Here's what you'll learn:



Let's dive into making your application visually appealing and user-friendly with a dark theme!

Hey there, fellow developers! 👋 Are you ready to take your Next.js app to the next level with a slick dark theme? You're in the right place! In this tutorial, we're going to walk through the process of adding a dark mode to your Next.js project using Tailwind CSS. Trust me, your users' eyes will thank you later!

Why Dark Mode Matters


Before we dive in, let's talk about why dark mode is more than just a trendy feature. It's not only easier on the eyes, especially in low-light conditions, but it can also help conserve battery life on OLED screens. Plus, let's be honest – it looks pretty cool too!

Step 1: Set Up Your Next.js Project

First things first, let's get our Next.js project up and running. If you already have a project, feel free to skip ahead. For the rest of us, open your terminal and run these commands:


npx create-next-app@latest my-dark-theme-app
cd my-dark-theme-app

This will create a new Next.js app in a folder called my-dark-theme-app and navigate you into that directory. The create-next-app tool will ask you a few questions – feel free to customize your setup but make sure you select "Yes" when it asks about using Tailwind CSS.


Step 2: Install and Configure Tailwind CSS

Alright, now that we've got our Next.js project set up, it's time to bring in the star of our show – Tailwind CSS! If you selected Tailwind CSS during the project setup, you might already have it installed. But don't worry if you didn't; we've got you covered.


Run this command in your terminal:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p


Step 3: Configure Tailwind CSS for Dark Mode 🌓

Alright, fellow night owls! 🦉 It's time to flip the switch and enable dark mode in our Tailwind configuration. This is where the magic begins!

Open up your tailwind.config.js file and let's make some changes:

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: 'class', // Enable dark mode with class
  content: [
    './app/**/*.{js,ts,jsx,tsx}',
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}


What's new here? 🤔

  1. We've added darkMode: 'class' - this tells Tailwind to use the class strategy for dark mode. It's like giving your app a cool pair of sunglasses! 😎

  2. We've expanded the content array to include all possible file paths. This ensures Tailwind can find and style all your components, no matter where they're hiding!

  3. With this small but mighty change, we've laid the groundwork for our dark-mode adventure. In the next step, we'll create a toggle to switch between light and dark modes. Get ready to see your app in a whole new light... or should I say, darkness! 🌚

    Step 5: Implement Dark Mode Toggle

    Now we're getting to the fun part - creating a toggle to switch between light and dark modes! We'll create a new component called ThemeManager to handle this.💪

    First, create a new file called ThemeManger.tsx in your components directory. We'll make this a client component so we can use React hooks and render changes on the client side without reloading the whole page.

    Here's the code for our ThemeManger component:

"use client";
import { useEffect, useState } from "react";

const ThemeManager: React.FC = (): JSX.Element => {
  const [theme, setTheme] = useState(
    typeof window !== "undefined" && localStorage.theme
      ? localStorage.theme
      : "system"
  );

  useEffect(() => {
    const root = window.document.documentElement;

    const removeOldThemes = () => {
      root.classList.remove("light", "dark");
    };

    if (
      theme === "dark" ||
      (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches)
    ) {
      removeOldThemes();
      root.classList.add("dark");
    } else {
      removeOldThemes();
      root.classList.add("light");
    }

    if (theme !== "system") {
      localStorage.setItem("theme", theme);
    } else {
      localStorage.removeItem("theme");
    }
  }, [theme]);

  return (
    <div className="flex justify-end p-3">
      <select
        value={theme}
        onChange={(e) => setTheme(e.target.value)}
        className="mr-2 cursor-pointer dark:bg-slate-800
 bg-white p-2 rounded-md border border-black
 dark:border-white"
      >
        <option
          value="light"
          className={`cursor-pointer px-4 py-3 mr-2 ${
            theme === "light" && "bg-gray-200"
          }`}
          onClick={() => setTheme("light")}
        >
          Light
        </option>
        <option
          value="dark"
          className={`cursor-pointer px-4 py-3 mr-2 ${
            theme === "dark" && "bg-gray-800 text-white"
          }`}
          onClick={() => setTheme("dark")}
        >
          Dark
        </option>
        <option
          value="system"
          className={`cursor-pointer px-4 py-3 ${
            theme === "system" && "bg-gray-400 text-white"
          }`}
          onClick={() => setTheme("system")}
        >
          System
        </option>
      </select>
    </div>
  );
};

export default ThemeManager;


Let's break down what's happening here:

  1. 1. 🧠 We use the useState hook to manage our theme state. It initially checks localStorage for a saved theme, defaulting to "system" if none is found.

  2. 2. 🔄 The useEffect hook runs whenever the theme changes. It handles:

    • • Removing old theme classes

    • • Adding the new theme class ('light' or 'dark')

    • • Checking system preferences when set to "system"

    • • Saving the theme to localStorage (or removing it if set to "system")

  3. 3. 🎨 We render a select element with options for Light, Dark, and System themes. The component uses Tailwind classes to style itself based on the current theme.

This component gives users the power to choose their preferred theme or sync with their system preferences. It's like a light switch for your app! 💡

In the next step, we'll integrate this ThemeManger into our Navbar and start applying dark mode styles to our pages. Get ready to see your app transform before your eyes! 👀✨


Kindly import the ThemeManger file into your Navbar and adjust as per your requirement while you are reading this blog if you check the navbar in the top right side I have already implemented the theme in this blog NextJs App which you can toggle.


Step 6: Change text or background color as per the theme selected

The coolest part of using the dark theme with a Tailwind CSS is that it will be available to the whole app and you can just change the text color or background color just by using dark: to implement color in the dark mode and without dark mode it will be implemented for the light mode. See the below image how to change color based on theme.


Conclusion

Congratulations, developer! 🎉 You've successfully navigated the world of dark mode implementation in Next.js with Tailwind CSS. Let's recap what we've accomplished:

  1. • Set up a Next.js project

  2. • Installed and configured Tailwind CSS

  3. • Enabled dark mode in Tailwind

  4. • Created a nifty ThemeManager component

  5. • Applied dark mode styles to our pages


Additional Resources 📚


Want to dive deeper into the dark mode, Next.js, or Tailwind CSS? Check out these fantastic resources:


  1. Next.js Documentation - The official guide for all things Next.js

  2. Tailwind CSS Dark Mode Guide - Tailwind's official documentation on dark mode

  3. A Complete Guide to Dark Mode on the Web - An in-depth look at implementing dark mode

  4. Accessibility and Dark Mode - Understanding the accessibility implications of dark mode

Remember, the best way to learn is by doing. So keep experimenting, keep building, and most importantly, have fun with it!

Happy coding, and may your dark mode be ever stylish and user-friendly! 😎🌙