How to Integrate Dark Mode and Light Mode Toggle in Next.js with Tailwind CSS
Implement dynamic dark mode and light mode in Next.js with Tailwind CSS to improve user experience, accessibility, and visual customization.
Offering users the ability to switch between light and dark themes is a standard practice in modern web development. Tailwind CSS, a utility-first CSS framework, simplifies the implementation and customization of themes, including dynamic dark mode switching.
This tutorial integrates information from multiple sources to guide you through setting up Tailwind CSS with React and Next.js, configuring dynamic dark mode functionality, and ensuring seamless theme transitions.
Prerequisites
Ensure you have the following prerequisites met before proceeding:
- Basic knowledge of React, Next.js, and JavaScript
- Node.js installed on your development machine
- Create React App or a similar React setup for React applications
- Next.js setup for Next.js applications
Step 1: Setting Up Tailwind CSS
- Installation: Begin by installing Tailwind CSS and its dependencies using npm or yarn:
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
- Initialization: Initialize Tailwind CSS configuration by executing:
npx tailwindcss init
- Configuration: Modify
tailwind.config.js
to enable dark mode variants based on class:
// tailwind.config.js
module.exports = {
darkMode: 'class', // Enable dark mode variant based on class
// Additional configuration options
};
Step 2: Creating the Theme Provider Component
Develop a ThemeProvider
component using React context to manage and dynamically switch themes.
// components/features/ThemeProvider.js
import { createContext, useState, useEffect, useContext } from 'react';
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('system');
useEffect(() => {
const storedTheme = localStorage.getItem('theme') || 'system';
setTheme(storedTheme);
applyTheme(storedTheme);
}, []);
const applyTheme = (theme) => {
const root = document.documentElement;
const isDarkMode = theme === 'dark' || (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
root.classList.toggle('dark', isDarkMode);
root.classList.toggle('light',!isDarkMode);
};
const toggleTheme = (newTheme) => {
setTheme(newTheme);
localStorage.setItem('theme', newTheme);
applyTheme(newTheme);
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
Step 3: Implementing Dynamic Dark Mode in Next.js Pages
Integrate the ThemeProvider
and ThemeToggle
components into your Next.js pages to facilitate theme toggling.
Updating globals.css
for Global Styles
Adjust globals.css
to define global styles and support dark mode:
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb)) rgb(var(--background-start-rgb));
}
@layer utilities {
.text-balance {
text-wrap: balance;
}
}
Creating a ThemeToggle
Component
Develop a ThemeToggle
component to allow users to switch themes:
// components/features/ThemeToggle.js
import { useTheme } from './ThemeProvider';
const ThemeToggle = () => {
const { theme, toggleTheme } = useTheme();
const handleChange = (event) => {
toggleTheme(event.target.value);
};
return (
<div className="p-4">
<select value={theme} onChange={handleChange} className="p-2 bg-green-500 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-green-300">
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="system">System</option>
</select>
</div>
);
};
export default ThemeToggle;
Integrating Layout Component
Wrap your entire Next.js application with the ThemeProvider
in a Layout
component for consistent theming:
// components/Layout.js
import { Inter } from 'next/font/google';
import './globals.css';
import { ThemeProvider } from './features/ThemeProvider';
const inter = Inter({ subsets: ['latin'] });
const Layout = ({ children }) => {
return (
<html lang="en">
<body className={inter.className}>
<ThemeProvider>
{children}
</ThemeProvider>
</body>
</html>
);
};
export default Layout;
Step 4: Applying Tailwind Classes for Dynamic Dark Mode
After setting up the dynamic dark mode functionality, the next step is to utilize Tailwind CSS classes within your React components. This allows you to create a responsive and visually appealing interface that adapts to the selected theme.
Example Implementation
Below is an example of how to apply Tailwind CSS classes in a React component to support dynamic dark mode. This example assumes you have already implemented the ThemeProvider
and useTheme
hook as described in the previous steps.
// src/App.js or any other component file
import { useTheme } from './features/ThemeProvider';
const App = () => {
const { theme } = useTheme();
return (
<div className={`bg-white dark:bg-gray-800 min-h-screen ${theme}`}>
<header className="p-4 bg-blue-500 dark:bg-gray-900">
<h1 className="text-2xl text-white dark:text-gray-100">Dynamic Dark Mode with Tailwind CSS</h1>
</header>
<main className="container mx-auto py-8">
<p className="text-gray-800 dark:text-white">
Hello, world This is a demonstration of Tailwind CSS with dynamic dark mode switching in React.
</p>
{/* Add your components and content here */}
</main>
</div>
);
};
export default App;
In this example, the App
component uses the useTheme
hook to access the current theme. The className
attribute of the outermost <div>
dynamically changes based on the current theme (light
, dark
, or system
).
Tailwind CSS classes prefixed with dark:
are applied automatically when the dark mode is active, thanks to the darkMode
configuration in tailwind.config.js
.
This approach allows you to design components that seamlessly adapt to both light and dark themes, enhancing the user experience across different environments and preferences.
Conclusion
By following these steps, you've successfully integrated Tailwind CSS with dynamic dark mode switching in a React application. Users can now toggle between light and dark modes seamlessly, with Tailwind's utility-first approach making it easy to style components based on the current theme.
Customize styles further to match your design preferences, ensuring a cohesive and accessible user experience across different themes.
Related Tags
Recommended
2m · 6min read
Web Development
2m · 6min read
Build a Real-time Speech Recognition Search Box with Next.js and Tailwind CSS
Building a real-time speech recognition search box using Next.js, Tailwind CSS, and the react-speech-recognition library
2m · 5min read
Web Development
2m · 5min read
How to Show Customized Relative Time with JavaScript
Learn how to create a JavaScript function to display relative time (like "5min ago" or "2y ago") by calculating the difference between the current date and an input date, converting it into various time units (seconds, minutes, hours, days, weeks, months, years), and returning the most appropriate unit as a string.
2m · 4min read
Web Development
2m · 4min read
How to Use Middleware in Next.js 14 for Route Protection
Implement middleware in Next.js 14 to protect routes, manage user authentication, handle role-based access. Middleware allows you to protect sensitive areas, such as user dashboards, while keeping public pages accessible to everyone.
2m · 5min read
Web Development
2m · 5min read
State Context vs Redux in React.js: When to Use Each One?
Learn the key differences between React's Context API and Redux for effective state management in your React.js applications, and discover which solution suits your project best.
2m · 4min read
Web Development
2m · 4min read
Build a Reusable Navbar Component for Multiple Pages Using HTML, CSS, and JavaScript
In this tutorial, we learned how to create a reusable navbar component using HTML, CSS, and JavaScript by dynamically loading the navbar into multiple pages, ensuring consistency and simplifying maintenance across the website.
3m · 4min read
Web Development
3m · 4min read
How to Integrate Dark Mode and Light Mode Toggle in Next.js with Tailwind CSS
Implement dynamic dark mode and light mode in Next.js with Tailwind CSS to improve user experience, accessibility, and visual customization.
4m · 6min read
Web Development
4m · 6min read
Cross-Origin Resource Sharing (CORS): How To Fix CORS
Cross-Origin Resource Sharing (CORS) is a browser mechanism that enables controlled access to resources from different domains, extending the same-origin policy while providing potential for cross-domain attacks if improperly configured.
4m · 5min read
Web Development
4m · 5min read
TypeScript Types vs Interfaces
Types vs Interfaces: Types in TypeScript are more flexible and can define a wider range of data types, including primitives, unions, intersections, tuples, and more, while interfaces are primarily used to describe the shape of objects and support declaration merging and extending, making them ideal for object-oriented programming and complex data structures
5m · 3min read
Web Development
5m · 3min read
The this Keyword in JavaScript
The this keyword in JavaScript is a reference to the object that a function is a property of. It's a fundamental concept in JavaScript, especially in object-oriented programming. Unlike in languages like Java, C#, or PHP, where this typically refers to the current instance of the class, JavaScript's this behaves differently and can be quite versatile.
6m · 8min read
Web Development
6m · 8min read
30 Common CSS Mistakes
30 CSS common mistakes we make includes: complicating selectors,Overuse of the “!important” declaration, Mishandling the z-index property, Duplicating code, Relying solely on color names and more