Want to let users change your website's look instantly? Here's how to do it with Tailwind CSS:
- Set up Tailwind CSS for themes
- Create a theme context
- Build a theme toggle button
- Use CSS variables for flexible themes
- Implement user preference detection
- Save and load theme choices
Key benefits:
- Improves accessibility
- Enhances user experience
- Maintains brand consistency
Quick setup:
npx create-react-app my-theme-switcher --template typescript
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure tailwind.config.js
:
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {
colors: {
primary: 'var(--color-primary)',
secondary: 'var(--color-secondary)',
background: 'var(--color-background)',
text: 'var(--color-text)',
},
},
},
plugins: [],
}
This guide will show you how to create a smooth, accessible theme switcher using Tailwind CSS and React.
Related video from YouTube
What you need to know first
Before we jump into dynamic theme switching with Tailwind CSS, let's cover the basics:
Tailwind CSS essentials
You should know:
- Utility classes
- Responsive design
- Customization options
Adam Wathan, Tailwind's creator, says: "Tailwind's utility-first approach makes it incredibly easy to build flexible, maintainable user interfaces."
JavaScript and React fundamentals
You'll need:
- JavaScript basics
- React components and hooks
- State management
Setting up your environment
Here's a quick setup:
2. Create a new React project:
npx create-react-app my-theme-switcher --template typescript
3. Install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Add to tailwind.config.js
:
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
5. Add Tailwind directives to src/index.css
:
@tailwind base;
@tailwind components;
@tailwind utilities;
6. Start your server:
npm start
Now you're ready to build your dynamic theme switcher!
Setting up Tailwind CSS for dynamic themes
Here's how to set up Tailwind CSS for dynamic themes:
Configure Tailwind CSS
- Install Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
- Update
tailwind.config.js
:
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {
colors: {
primary: 'var(--color-primary)',
secondary: 'var(--color-secondary)',
background: 'var(--color-background)',
text: 'var(--color-text)',
},
},
},
plugins: [],
}
- Add Tailwind directives to your main CSS file:
@tailwind base;
@tailwind components;
@tailwind utilities;
Create custom color schemes
- Define base colors in your main CSS file:
:root {
--color-primary: 66, 133, 244;
--color-secondary: 52, 168, 83;
--color-background: 255, 255, 255;
--color-text: 0, 0, 0;
}
- Create theme files (e.g.,
dark-theme.css
):
[data-theme="dark"] {
--color-primary: 138, 180, 248;
--color-secondary: 129, 201, 149;
--color-background: 32, 33, 36;
--color-text: 255, 255, 255;
}
- Import theme files in your main CSS:
@import "themes/dark-theme.css";
@import "themes/light-theme.css";
To switch themes, use JavaScript:
document.documentElement.setAttribute('data-theme', 'dark');
This setup allows for easy theme switching and smooth transitions.
Building theme switching functionality
Let's create a theme switcher for your Tailwind CSS project. Here's how:
Make a theme context
First, set up a React context:
import { createContext, useContext, useState, useEffect } from "react";
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [darkMode, setDarkMode] = useState(false);
useEffect(() => {
document.documentElement.setAttribute(
"data-theme",
darkMode ? "dark" : "light"
);
}, [darkMode]);
const toggleTheme = () => {
setDarkMode((prevMode) => !prevMode);
};
return (
<ThemeContext.Provider value={{ darkMode, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => useContext(ThemeContext);
This context manages the theme state across your app.
Create a theme toggle button
Now, build a component for switching themes:
import { useTheme } from "./ThemeContext";
const ThemeToggle = () => {
const { darkMode, toggleTheme } = useTheme();
return (
<button
onClick={toggleTheme}
className="px-4 py-2 rounded bg-gray-200 dark:bg-gray-700"
>
{darkMode ? "Light Mode" : "Dark Mode"}
</button>
);
};
Change themes on user action
Update your CSS:
:root {
--bg-color: white;
--text-color: black;
}
[data-theme="dark"] {
--bg-color: black;
--text-color: white;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
}
Wrap your app with the ThemeProvider
:
import { ThemeProvider } from "./ThemeContext";
function App() {
return (
<ThemeProvider>
<div className="App">
<ThemeToggle />
{/* Your app content */}
</div>
</ThemeProvider>
);
}
Now users can switch themes with a click, instantly updating the UI.
sbb-itb-55aadfa
Using CSS Variables for Flexible Themes
CSS variables make theme switching in Tailwind CSS a breeze. Here's how to set them up:
Setting Theme Colors
In your global CSS file, define variables in the :root
selector:
:root {
--color-bgBase: 39deg 85% 95%;
--color-content: 0deg 0% 20%;
}
@media (prefers-color-scheme: dark) {
:root {
--color-bgBase: 240deg 27% 18%;
--color-content: 210deg 14% 53%;
}
}
Combining with Tailwind
In tailwind.config.js
, add to the theme
section:
module.exports = {
theme: {
colors: {
bgBase: 'hsl(var(--color-bgBase) / <alpha-value>)',
content: 'hsl(var(--color-content) / <alpha-value>)',
}
}
}
Now use these colors in components:
function SignIn() {
return (
<button className="py-1 px-2 bg-bgBase text-content rounded">
Sign In
</button>
);
}
This approach eliminates the need for dark:
classes on every component.
For more complex themes, define additional variables:
:root {
--primary: #742a2a;
--secondary: #e53e3e;
}
.th-blue {
--primary: #2a4365;
--secondary: #3182ce;
}
Use them in your Tailwind config:
module.exports = {
theme: {
colors: {
'th-primary': 'var(--primary)',
'th-secondary': 'var(--secondary)'
}
}
}
Apply themes easily in HTML:
<div class="bg-th-primary">
<h3 class="bg-th-secondary text-th-primary">Join our mailing list</h3>
<button class="bg-th-secondary" type="button">Sign up</button>
</div>
This method makes theme switching smooth and manageable.
Tips for good theme switching
Keep performance in mind
When adding theme switching, you need to make it fast. Here's how:
1. Use CSS variables for colors
This cuts down on the changes needed when switching themes.
2. Load only what you need
Only grab the CSS for the current theme. Load other stuff as needed.
3. Stop the flicker
Add this to your HTML's <head>
to avoid that ugly flash of unstyled content:
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.classList.add(theme);
4. Pick efficient selectors
Tailwind CSS is great for this. It makes tiny, fast CSS files.
Make themes accessible
Your themes should work for everyone. Here's how:
1. Check color contrast
Make sure text is easy to read on your background. Use tools like WebAIM's contrast checker.
2. Make it keyboard-friendly
Your theme toggle should work with a keyboard. Here's a good example:
<button type="button" id="theme-toggle" role="switch" aria-checked="false" class="flex w-14 h-8 p-1 rounded-full bg-slate-400 transition-colors duration-200 ease-in-out overflow-hidden outline-none focus-visible:ring focus-visible:ring-purple-400 aria-checked:bg-blue-400">
<span class="w-6 h-6 rounded-full bg-white"></span>
</button>
<label for="theme-toggle">Toggle theme</label>
3. Help screen readers
Use ARIA attributes to tell screen readers about theme changes.
4. Follow user preferences
Use prefers-color-scheme
to match the user's system color scheme:
@media (prefers-color-scheme: dark) {
:root {
--color-bgBase: 240deg 27% 18%;
--color-content: 210deg 14% 53%;
}
}
5. Keep it consistent
Don't change your layout between themes. It'll confuse people.
Working with user preferences
Let's dive into building a theme-switching feature with Tailwind CSS that respects user choices and system settings.
Checking system color scheme
Want to know if a user prefers dark mode? Use this:
const prefersDarkMode = () => window.matchMedia('(prefers-color-scheme: dark)').matches;
For light mode:
const prefersLightMode = () => window.matchMedia('(prefers-color-scheme: light)').matches;
These functions tap into the user's system settings. Simple, right?
Saving and loading user theme choices
To keep themes consistent, we'll use localStorage. Here's how:
// On page load
const savedTheme = localStorage.getItem('theme');
const systemPreference = prefersDarkMode() ? 'dark' : 'light';
const initialTheme = savedTheme || systemPreference;
document.documentElement.classList.add(initialTheme);
// When user changes theme
function toggleTheme() {
const newTheme = document.documentElement.classList.contains('dark') ? 'light' : 'dark';
document.documentElement.classList.remove('light', 'dark');
document.documentElement.classList.add(newTheme);
localStorage.setItem('theme', newTheme);
}
This code checks for a saved theme first, then falls back to the system preference.
Using React? Here's a hook-based approach:
function App() {
const [theme, setTheme] = useState(() => {
return localStorage.getItem('theme') || 'light';
});
useEffect(() => {
localStorage.setItem('theme', theme);
document.documentElement.classList.toggle('dark', theme === 'dark');
}, [theme]);
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
);
}
This keeps the theme consistent across page reloads and respects user choices. Easy peasy!
Conclusion
Tailwind CSS dynamic theme switching is a powerful tool for web developers. It allows you to create designs that adapt to user preferences.
Here's what we've covered:
- Tailwind CSS simplifies theme switching with its dark mode utility
- CSS variables are crucial for flexible themes
- Considering user preferences enhances the overall experience
Good theme switching goes beyond aesthetics:
- It improves accessibility for users with different visual needs
- It boosts user experience by offering choice
- It maintains brand consistency across devices
Want to get started? Here's a simple approach:
1. Set up a basic light/dark toggle
2. Get user feedback
3. Expand your themes based on what you learn
Tailwind CSS provides the foundation. Now it's your turn to create themes that impress your users and make your site unique.
FAQs
How to toggle Tailwind dark mode?
Here's how to set up Tailwind dark mode:
1. Enable dark mode
Add this to your tailwind.config.js
:
module.exports = {
darkMode: 'class',
// ...
}
2. Create a toggle
<input type="checkbox" id="dark-mode-toggle" class="light-switch">
3. Add JavaScript
const lightSwitches = document.querySelectorAll('.light-switch');
lightSwitches.forEach((lightSwitch, i) => {
if (localStorage.getItem('dark-mode') === 'true') {
lightSwitch.checked = true;
}
lightSwitch.addEventListener('change', () => {
const { checked } = lightSwitch;
lightSwitches.forEach((el, n) => {
if (n !== i) el.checked = checked;
});
if (checked) {
document.documentElement.classList.add('dark');
localStorage.setItem('dark-mode', true);
} else {
document.documentElement.classList.remove('dark');
localStorage.setItem('dark-mode', false);
}
});
});
This code remembers user preferences and updates the theme.
4. Style for dark mode
Use the dark:
prefix in your HTML:
<div class="bg-white dark:bg-gray-900 text-black dark:text-white">
<!-- Content goes here -->
</div>
That's it! You've now got a working dark mode toggle for your Tailwind site.