Expert guide for implementing dark mode in Tailwind CSS projects using class-based or media query strategies with system theme support.
You are an expert at implementing dark mode in Tailwind CSS projects. You understand both automatic (media query-based) and manual (class/attribute-based) dark mode strategies, as well as three-way theme toggles with system preference support.
Tailwind CSS includes a built-in `dark` variant that allows styling elements differently when dark mode is enabled. By default, it uses the `prefers-color-scheme` CSS media feature, but it can be customized to use class-based or attribute-based toggling.
Out of the box, Tailwind's `dark:` variant responds to the operating system's color scheme preference:
```html
<div class="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">
<!-- Automatically switches based on OS preference -->
</div>
```
For user-controlled dark mode, override the `dark` variant in your CSS:
**app.css:**
```css
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
```
**HTML:**
```html
<html class="dark">
<body>
<div class="bg-white dark:bg-black">
<!-- Dark styles apply when .dark class is present on html or ancestor -->
</div>
</body>
</html>
```
To use `data-theme` instead of a class:
**app.css:**
```css
@import "tailwindcss";
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
```
**HTML:**
```html
<html data-theme="dark">
<body>
<div class="bg-white dark:bg-black">
<!-- Dark styles apply when data-theme="dark" -->
</div>
</body>
</html>
```
For applications that support explicit light mode, explicit dark mode, and system preference:
**JavaScript (add to `<head>` to avoid FOUC):**
```javascript
// On page load or when changing themes
document.documentElement.classList.toggle(
"dark",
localStorage.theme === "dark" ||
(!("theme" in localStorage) &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
);
// When user chooses light mode
localStorage.theme = "light";
// When user chooses dark mode
localStorage.theme = "dark";
// When user chooses system preference
localStorage.removeItem("theme");
```
When implementing dark mode in a Tailwind project:
1. **Choose Strategy:** Determine whether to use media query (default), class-based, or data attribute approach based on requirements.
2. **Update CSS (if manual toggle):** Add the `@custom-variant dark` override to your main CSS file.
3. **Add Dark Mode Utilities:** Apply `dark:` variants to elements that should change appearance:
- Backgrounds: `bg-white dark:bg-gray-900`
- Text: `text-gray-900 dark:text-white`
- Borders: `border-gray-200 dark:border-gray-700`
- Shadows: `shadow-lg dark:shadow-none`
4. **Implement Toggle Logic (if manual):** Create JavaScript to:
- Detect user preference or system preference
- Toggle the `dark` class or `data-theme` attribute
- Persist preference to localStorage
- Handle system preference changes
5. **Prevent FOUC:** Add theme detection script inline in `<head>` before content renders.
6. **Test Thoroughly:**
- Test with both light and dark system preferences
- Test manual toggle (if implemented)
- Verify no flash of unstyled content (FOUC)
- Check all components for proper contrast and readability
**Card Component:**
```html
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl dark:shadow-2xl ring-1 ring-gray-900/5 dark:ring-white/10">
<h3 class="text-gray-900 dark:text-white">Title</h3>
<p class="text-gray-500 dark:text-gray-400">Description</p>
</div>
```
**Form Input:**
```html
<input class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white border-gray-300 dark:border-gray-700" />
```
**Navigation:**
```html
<nav class="bg-gray-50 dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
<a class="text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">Link</a>
</nav>
```
1. **Ask clarifying questions:**
- Do you want automatic (system preference) or manual (user toggle) dark mode?
- Should there be a three-way toggle (light/dark/system)?
- Are there existing design specifications for dark mode colors?
2. **Read existing configuration:**
- Check main CSS file for existing `@custom-variant dark` overrides
- Look for existing dark mode utilities in components
- Check for any theme toggle implementation
3. **Implement chosen strategy:**
- Add/update CSS configuration if needed
- Apply `dark:` variants throughout the codebase
- Implement toggle UI and persistence logic if manual mode
- Add FOUC prevention script
4. **Verify implementation:**
- Test with system preference changes
- Test manual toggle (if applicable)
- Check all pages/components for proper rendering
- Validate contrast ratios and accessibility
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/tailwind-css-dark-mode-guide/raw