DEV Community

Nana K.
Nana K.

Posted on • Edited on

Setting Up Accessibility Features (Dark Mode) in Next JS (With TailwindCSS)

In my journey to incorporate the dark mode feature into Next.js, I vividly recall my initial attempt using a familiar approach from React—the useContext hook. Unfortunately, this method proved unsuccessful, leading me to an extensive exploration marked by numerous hours of trial and error. Despite facing challenges and encountering errors, persistence ultimately paid off as I uncovered the correct path to seamlessly integrate dark mode functionality into Next.js.

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.

Setting Up

To commence, ensure you have a Next.js application with Tailwind CSS configured. Fortunately, simplifying this process is the npx create-next-app@latest command, which conveniently sets up a Next.js app pre-configured with Tailwind. Execute this command to effortlessly initialize and set up your Next.js application.

Install next-themes

next-themes is:

An abstraction for themes in your Next.js app.

Implementing Dark Mode

Implementing dark mode in Next.js is effortlessly achieved through the dark variant in Tailwind CSS. Simply prefix properties with dark: to designate them for dark mode. For instance, utilizing dark:text-red-700 adjusts the text color to red-700 when the theme is switched to dark.

By default, Next.js aligns with system preferences for theme selection. Nevertheless, to seamlessly toggle between light and dark modes, configure the darkMode strategy to 'class' in the tailwind.config.js file:
darkMode: "class",

Setup your ThemeProvider

next-themes needs a ThemeProvider to manage themes in your project. You can either create a special component or wrap your main layout with the ThemeProvider component from next-themes to make it work.

Custom Component (Import this into your layout.tsx file):

"use client";
import * as React from "react";
import { ThemeProvider } from "next-themes";

type Props = {
  children?: React.ReactNode;
};

export function ThemeProvider({children}) {
  return (
    <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
      {children}
    </ThemeProvider>
  );
}
Enter fullscreen mode Exit fullscreen mode

Using the Existing Component in your layout.tsx file:

import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "My NextJS Web App",
  description: "Setting up Dark Mode in NextJS!",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}
Enter fullscreen mode Exit fullscreen mode

Set up some Global Styles:

Next, let's set up some global styles for things like background color and text appearance when switching modes. We'll handle this in our globals.css file.

@layer base {
  body {
    @apply dark:bg-[#0a0a0a] 
        bg-[#edf6f9];
  }
}
Enter fullscreen mode Exit fullscreen mode

Ensuring your application is accessible in both light and dark modes is crucial. When selecting text and background colors, prioritize adequate contrast. You can evaluate your application's accessibility with tools such as the Accessibility Insights browser extension.

Add your ThemeToggle Component:

Now, we require a component for seamless theme switching. Utilizing the useTheme hook enables us to determine the current theme, and incorporating an onClick event facilitates state transitions. Initially, we establish our theme to align with the system theme.

"use client";
import React from "react";
import { useTheme } from "next-themes";
import { RiMoonLine, RiSunLine } from "react-icons/ri";

const DarkModeToggle = () => {
  const { theme, setTheme } = useTheme();
  return (
    <button
      onClick={() => (theme == "dark" ? setTheme("light") : setTheme("dark"))}>
      {theme === "light" ? (
        <RiMoonLine/>
      ) : (
        <RiSunLine/>
      )}
    </button>
  );
};

export default DarkModeToggle;
Enter fullscreen mode Exit fullscreen mode

What's next

Import the ThemeToggle Component into your application, and you're all set! It's essential to note that to fully experience the capabilities of next-themes, you'll need to incorporate styles for dark mode by using the dark: prefix throughout your entire app. That concludes the setup!

Top comments (2)

Collapse
 
gandalf-hash profile image
Johannes Phetoane

Thanks, what a clean approach!

Collapse
 
topboyasante profile image
Nana K.

thanks!