Introduction
Dark mode is a highly sought-after feature in modern web applications, offering an aesthetically pleasing alternative to the default light theme and reducing eye strain in low-light environments. In this tutorial, we'll guide you through building a dark mode toggle using Tailwind CSS and React Context. By the end of this tutorial, you'll have a fully functional dark mode feature that you can easily integrate into any React project.
Prerequisites
Before we start, ensure you have a basic understanding of the following:
React: Familiarity with React components, hooks, and context API.
Tailwind CSS: Basic knowledge of utility-first CSS frameworks.
Step 1: Setting Up Your React Project with Tailwind CSS
If you don't already have a React project set up, let's create a new one and install Tailwind CSS.
- Create a new React project:
npx create-react-app dark-mode-toggle
cd dark-mode-toggle
- Install Tailwind CSS: Follow the official Tailwind CSS installation guide for Create React App:
npm install -D tailwindcss
npx tailwindcss init
- Configure Tailwind: In the
tailwind.config.js
file, add the following content
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
- Add Tailwind to your CSS: Replace the content of
src/index.css
with:
@tailwind base;
@tailwind components;
@tailwind utilities;
- Start the development server:
npm start
Step 2: Create a Theme Context
We’ll use React Context to manage the theme state across the entire application.
- Create
ThemeContext.js
in thesrc
directory:
import React, { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState("light");
const toggleTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<div className={theme === "light" ? "light-theme" : "dark-theme"}>
{children}
</div>
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
This context provides a theme
state and a toggleTheme
function to switch between light and dark themes.
Step 3: Implement Dark Mode Styles with Tailwind CSS
Next, we'll define styles for light and dark themes using Tailwind CSS utility classes.
- Update
tailwind.config.js
to support dark mode:
module.exports = {
darkMode: 'class', // or 'media' or 'class'
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
darkBg: "#1a202c",
darkText: "#f7fafc",
lightBg: "#ffffff",
lightText: "#1a202c",
},
},
},
plugins: [],
}
- Apply theme classes in your components: Update your
App.js
file to use the theme context and apply Tailwind's utility classes:
import React from 'react';
import { ThemeProvider, useTheme } from './ThemeContext';
const App = () => {
const { theme, toggleTheme } = useTheme();
return (
<div className={`min-h-screen ${theme === 'light' ? 'bg-lightBg text-lightText' : 'bg-darkBg text-darkText'}`}>
<header className="p-4">
<h1 className="text-2xl font-bold">Dark Mode Toggle</h1>
<button
onClick={toggleTheme}
className="mt-4 px-4 py-2 bg-gray-800 text-white rounded"
>
Toggle Dark Mode
</button>
</header>
</div>
);
};
const Root = () => (
<ThemeProvider>
<App />
</ThemeProvider>
);
export default Root;
Step 4: Test Your Dark Mode Toggle
With everything set up, there will be a button "Toggle Dark Mode" in your application. When you click it, the theme should switch between light and dark modes, with the background and text colors updating accordingly.
Step 5: Customizing and Extending
Feel free to customize the colors in your Tailwind config to match your project's design system. You can also extend this example by adding more components that respond to the theme change, such as navigation bars, footers, and cards.
Conclusion
In this tutorial, we built a dark mode toggle using React Context and Tailwind CSS. This approach allows for a clean, maintainable solution that can be easily integrated into any React project. As dark mode becomes more prevalent in modern web applications, having a reusable implementation like this one can greatly enhance the user experience.