install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/css-dark-mode" ~/.claude/skills/intense-visions-harness-engineering-css-dark-mode-916bfd && rm -rf "$T"
manifest:
agents/skills/codex/css-dark-mode/SKILL.mdsource content
Dark Mode with Tailwind
Implement dark mode with Tailwind's dark variant, CSS custom properties, and user preference detection
When to Use
- Adding dark mode to an existing Tailwind application
- Supporting system preference detection and manual theme switching
- Using CSS variables so that one set of utilities works in both themes
- Persisting the user's theme choice across sessions
Instructions
- Choose a strategy:
(manual toggle viaclass
class on.dark
) or<html>
(follows OS preference). Usemedia
for manual control.class - Define color tokens as CSS variables with light and dark values. Use Tailwind's
prefix for overrides.dark: - Prefer the CSS variable approach over per-element
classes — it scales better with many components.dark: - Detect the user's preference with
. Store their choice in localStorage.window.matchMedia('(prefers-color-scheme: dark)') - Apply the theme class before first paint to prevent flash of wrong theme (FOWT).
// tailwind.config.ts const config: Config = { darkMode: 'class', // Enable class-based dark mode // ... };
/* styles/globals.css */ @layer base { :root { --background: 255 255 255; --foreground: 17 24 39; --card: 249 250 251; --primary: 59 130 246; --muted: 107 114 128; --border: 229 231 235; } .dark { --background: 15 23 42; --foreground: 248 250 252; --card: 30 41 59; --primary: 96 165 250; --muted: 148 163 184; --border: 51 65 85; } }
// hooks/use-theme.ts import { useEffect, useState } from 'react'; type Theme = 'light' | 'dark' | 'system'; export function useTheme() { const [theme, setThemeState] = useState<Theme>(() => { if (typeof window === 'undefined') return 'system'; return (localStorage.getItem('theme') as Theme) ?? 'system'; }); useEffect(() => { const root = document.documentElement; function applyTheme(t: Theme) { if (t === 'system') { const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches; root.classList.toggle('dark', isDark); } else { root.classList.toggle('dark', t === 'dark'); } } applyTheme(theme); // Listen for OS preference changes const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); const handler = () => { if (theme === 'system') applyTheme('system'); }; mediaQuery.addEventListener('change', handler); return () => mediaQuery.removeEventListener('change', handler); }, [theme]); const setTheme = (t: Theme) => { setThemeState(t); localStorage.setItem('theme', t); }; return { theme, setTheme }; }
// Prevent flash of wrong theme — add to <head> in your HTML/layout <script dangerouslySetInnerHTML={{ __html: ` (function() { var theme = localStorage.getItem('theme'); if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) { document.documentElement.classList.add('dark'); } })(); `, }} />
Details
CSS variable approach vs
prefix:dark:
// Per-element dark: classes (verbose, repetitive) <div className="bg-white dark:bg-slate-800 text-gray-900 dark:text-gray-100 border-gray-200 dark:border-gray-700"> // CSS variable approach (clean, DRY) <div className="bg-background text-foreground border-border"> // Colors switch automatically via CSS variables
Approach comparison:
prefix: Simple, no CSS variables needed. Gets verbose with many elements.dark:- CSS variables: Define once, works everywhere. Best for design systems with many components.
- Both: Use CSS variables for common patterns,
for one-off overrides.dark:
Next.js with next-themes:
import { ThemeProvider } from 'next-themes'; function App({ children }) { return ( <ThemeProvider attribute="class" defaultTheme="system" enableSystem> {children} </ThemeProvider> ); }
Images and dark mode: Provide dark-mode variants for images, or use CSS filters:
<img className="dark:invert dark:brightness-90" src="/logo.svg" alt="Logo" /> // Or use next/image with dark mode source
Testing dark mode: In browser DevTools, toggle the
dark class on <html>. Or use DevTools > Rendering > Emulate CSS media feature prefers-color-scheme: dark.
Source
https://tailwindcss.com/docs/dark-mode
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.