FrontendNext.jsTailwind CSSDark ModeReactUI

Dark Mode in Next.js with Tailwind CSS: Complete Implementation

Implement a flicker-free dark mode in Next.js using Tailwind CSS dark class strategy with system preference detection and user toggle.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

October 7, 2024 8 min read

Approaches to Dark Mode in Next.js

There are two main approaches to dark mode in Next.js with Tailwind: the class strategy (add a dark class to the html element and toggle it with JavaScript) and the media strategy (use the prefers-color-scheme media query automatically). The class strategy is recommended because it gives users control to override their system preference — which is what most users expect from a modern website.

Configuring Tailwind for Dark Mode

In your tailwind.config.js, set darkMode: 'class'. Now all dark: variants in Tailwind (like dark:bg-gray-900 dark:text-white) only apply when an ancestor element has the dark class. Typically you add or remove this class on the html element. Build out your color scheme using both light and dark variants for every color in your design.

Avoiding Flash of Wrong Theme

The biggest challenge with dark mode in Next.js is preventing the flash of the wrong theme on page load. Because JavaScript runs after HTML renders, there is a brief moment where the page renders in light mode before switching to dark — this is jarring for dark mode users. Solve this by injecting an inline script in the <head> that reads localStorage before React hydrates and sets the dark class synchronously.

Using next-themes

The next-themes library handles all the complexity for you: it prevents flash, syncs with system preference, persists user choice to localStorage, and provides a ThemeProvider and useTheme hook. Install next-themes, wrap your app in ThemeProvider with attribute='class', and use the setTheme function from useTheme in your toggle button. This is the recommended approach for most Next.js projects.

Building the Theme Toggle Component

Create a ThemeToggle component that uses the useTheme hook from next-themes. Show a sun icon for light mode and a moon icon for dark mode. Use suppressHydrationWarning on the button to prevent React hydration mismatch warnings, since the theme cannot be known until after client-side JavaScript runs. Animate the icon transition with a smooth CSS transition for a polished feel.

Styling Tips for Dark Mode

Use CSS custom properties (variables) for your color palette and define dark mode overrides in a [data-theme=dark] selector or .dark selector. Avoid pure black (#000000) backgrounds in dark mode — use dark grays like #0f0f0f or #1a1a1a for better readability. Reduce image brightness slightly in dark mode with dark:brightness-90 to prevent images from being too harsh against dark backgrounds.

Share this article

All posts
#Next.js#Tailwind CSS#Dark Mode#React#UI
Abdur Razzak — Full Stack Web Developer
Available for projects

Need a React or Next.js Developer?