
dark-mode-design-expert
Master dark mode UI design with atmospheric theming, WCAG accessibility, and cross-platform best practices. Specializes in weather/sky/ocean-inspired color systems that adapt to time of day and environmental conditions.
- Installs
- 304
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/curiositech/some_claude_skills --skill dark-mode-design-expert- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads dark-mode-design-expert automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Dark Mode Design Expert
Master dark mode UI design with atmospheric theming, WCAG accessibility, and cross-platform best practices. Specializes in weather/sky/ocean-inspired color systems that adapt to time of day and environmental conditions.
When to Use This Skill
Activate on:
- "dark mode", "dark theme", "night mode"
- "theme switching", "light/dark toggle"
- "atmospheric UI", "weather theme", "sky gradient"
- "OLED optimization", "battery-friendly dark"
- "elevation in dark mode", "surface layering"
- "prefers-color-scheme", "color-scheme CSS"
- "contrast ratios dark mode", "accessibility dark theme"
NOT for:
- General color palette creation →
color-theory-palette-harmony-expert - Typography and font selection →
typography-expert - Component library architecture →
design-system-creator - Contrast auditing of specific colors →
color-contrast-auditor
The Science of Dark Mode
Why Dark Mode Exists
| Factor | Light Mode | Dark Mode | Winner |
|---|---|---|---|
| OLED Battery | 100% baseline | 39-47% savings at max brightness | Dark |
| Low Light Comfort | Eye strain, fatigue | Reduced glare | Dark |
| Bright Environment | Better readability | Washed out | Light |
| Astigmatism Users | Easier to read | Halation effect | Light |
| Focus/Immersion | Standard | Content pops forward | Dark |
| Sleep Hygiene | Blue light exposure | Reduced blue light | Dark |
Key Insight: Dark mode isn't universally better—it's contextually better. The best systems respect user preference AND adapt to environment.
Contrast Requirements (WCAG 2.1)
| Element Type | Minimum Ratio | Target Ratio | Notes |
|---|---|---|---|
| Body text | 4.5:1 | 7:1+ | AAA preferred for readability |
| Large text (≥24px) | 3:1 | 4.5:1+ | Headlines, hero text |
| UI components | 3:1 | 4.5:1+ | Borders, icons, focus rings |
| Disabled elements | None required | 2.5:1 | UX consideration |
| Decorative | None required | - | Pure aesthetic elements |
Dark Mode Gotcha: High contrast (21:1 pure white on black) causes more eye strain than moderate contrast (15:1). Target 12:1 to 16:1 for primary text.
The Three-Tier Token Architecture
Foundation: Primitives → Semantic → Component
/* ══════════════════════════════════════════════════════════════════
TIER 1: PRIMITIVES - Raw color values, never used directly
══════════════════════════════════════════════════════════════════ */
:root {
/* Neutrals */
--color-gray-50: #f8fafc;
--color-gray-100: #f1f5f9;
--color-gray-200: #e2e8f0;
--color-gray-300: #cbd5e1;
--color-gray-400: #94a3b8;
--color-gray-500: #64748b;
--color-gray-600: #475569;
--color-gray-700: #334155;
--color-gray-800: #1e293b;
--color-gray-900: #0f172a;
--color-gray-950: #020617;
/* Brand Colors */
--color-ocean-300: #7dd3fc;
--color-ocean-400: #38bdf8;
--color-ocean-500: #0ea5e9;
--color-ocean-600: #0284c7;
--color-ocean-700: #0369a1;
/* Atmospheric Colors (for weather theming) */
--color-twilight-deep: #0c1222;
--color-twilight-mid: #151b2e;
--color-twilight-surface: #1a1f3a;
--color-dawn-warm: #fef3c7;
--color-sunset-orange: #fb923c;
--color-storm-gray: #374151;
}
/* ══════════════════════════════════════════════════════════════════
TIER 2: SEMANTIC - Purpose-driven, theme-aware
══════════════════════════════════════════════════════════════════ */
/* Light Mode (Default) */
:root, :root.theme-light {
/* Text */
--color-text-primary: var(--color-gray-900); /* 15.3:1 on white */
--color-text-secondary: var(--color-gray-600); /* 7.0:1 on white */
--color-text-muted: var(--color-gray-500); /* 4.6:1 on white */
--color-text-inverse: var(--color-gray-50);
/* Backgrounds */
--color-bg-primary: #ffffff;
--color-bg-secondary: var(--color-gray-50);
--color-bg-elevated: #ffffff;
--color-bg-overlay: rgba(0, 0, 0, 0.5);
/* Surfaces (elevation system) */
--color-surface-base: #ffffff;
--color-surface-raised: #ffffff;
--color-surface-overlay: #ffffff;
/* Borders */
--color-border-default: var(--color-gray-200);
--color-border-muted: var(--color-gray-100);
--color-border-emphasis: var(--color-gray-300);
/* Interactive */
--color-interactive-primary: var(--color-ocean-600);
--color-interactive-hover: var(--color-ocean-700);
--color-interactive-focus: var(--color-ocean-500);
/* Elevation (shadows work in light mode) */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
--shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15);
}
/* Dark Mode */
:root.theme-dark {
/* Text - slightly off-white to reduce strain */
--color-text-primary: var(--color-gray-50); /* 15.3:1 on dark */
--color-text-secondary: var(--color-gray-300); /* 9.3:1 on dark */
--color-text-muted: var(--color-gray-400); /* 5.5:1 on dark */
--color-text-inverse: var(--color-gray-900);
/* Backgrounds - NOT pure black (#000) */
--color-bg-primary: var(--color-twilight-deep); /* #0c1222 */
--color-bg-secondary: var(--color-twilight-mid); /* #151b2e */
--color-bg-elevated: var(--color-twilight-surface); /* #1a1f3a */
--color-bg-overlay: rgba(0, 0, 0, 0.7);
/* Surfaces - LIGHTER for elevation (key dark mode principle) */
--color-surface-base: var(--color-twilight-deep);
--color-surface-raised: var(--color-twilight-mid);
--color-surface-overlay: var(--color-twilight-surface);
/* Borders - more visible in dark mode */
--color-border-default: rgba(255, 255, 255, 0.1);
--color-border-muted: rgba(255, 255, 255, 0.05);
--color-border-emphasis: rgba(255, 255, 255, 0.2);
/* Interactive - brighter for visibility */
--color-interactive-primary: var(--color-ocean-400);
--color-interactive-hover: var(--color-ocean-300);
--color-interactive-focus: var(--color-ocean-500);
/* Elevation - GLOW replaces shadows in dark mode */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4);
--shadow-md: 0 4px 8px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.5);
--shadow-xl: 0 12px 24px rgba(0, 0, 0, 0.6);
/* Glow effects (unique to dark mode) */
--glow-sm: 0 0 8px rgba(56, 189, 248, 0.2);
--glow-md: 0 0 16px rgba(56, 189, 248, 0.3);
--glow-lg: 0 0 32px rgba(56, 189, 248, 0.4);
}
/* ══════════════════════════════════════════════════════════════════
TIER 3: COMPONENT - Specific usage, consuming semantic tokens
══════════════════════════════════════════════════════════════════ */
:root {
/* Buttons */
--button-bg: var(--color-interactive-primary);
--button-text: var(--color-text-inverse);
--button-border: transparent;
--button-shadow: var(--shadow-sm);
/* Cards */
--card-bg: var(--color-surface-raised);
--card-border: var(--color-border-default);
--card-shadow: var(--shadow-md);
/* Inputs */
--input-bg: var(--color-bg-primary);
--input-border: var(--color-border-default);
--input-focus-ring: var(--color-interactive-focus);
}
Elevation in Dark Mode: The Critical Difference
Why Shadows Fail in Dark Mode
In light mode, shadows create depth by simulating light from above. In dark mode:
- Shadows become invisible against dark backgrounds
- Pure black shadows look like "holes"
- The illusion breaks completely
Material Design 3 Solution: Tonal Elevation
Instead of shadows, use lighter surface colors for elevated elements:
/* Light Mode: Shadows create elevation */
.card-light {
background: #ffffff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
/* Dark Mode: Surface color creates elevation */
.card-dark {
background: #1e1e1e; /* Elevated from #121212 base */
box-shadow: none; /* Or very subtle */
}
Elevation Scale (Material Design 3)
| Level | Light Mode | Dark Mode Surface | Overlay % |
|---|---|---|---|
| 0 (base) | #ffffff | #121212 | 0% |
| 1 | shadow-sm | #1e1e1e | 5% white |
| 2 | shadow-md | #232323 | 7% white |
| 3 | shadow-lg | #282828 | 8% white |
| 4 | shadow-xl | #2d2d2d | 9% white |
| 5 | shadow-2xl | #323232 | 11% white |
Implementation Pattern
:root.theme-dark {
/* Calculate overlay colors */
--elevation-1: color-mix(in srgb, white 5%, var(--color-bg-primary));
--elevation-2: color-mix(in srgb, white 7%, var(--color-bg-primary));
--elevation-3: color-mix(in srgb, white 8%, var(--color-bg-primary));
--elevation-4: color-mix(in srgb, white 9%, var(--color-bg-primary));
--elevation-5: color-mix(in srgb, white 11%, var(--color-bg-primary));
}
.card {
background: var(--elevation-2);
}
.modal {
background: var(--elevation-4);
}
.dropdown {
background: var(--elevation-3);
}
CSS Implementation Patterns
Modern Approach: prefers-color-scheme + light-dark()
/* 1. Set color-scheme for native element styling */
:root {
color-scheme: light dark;
}
/* 2. Use light-dark() for inline theming (2024+ browsers) */
.card {
background: light-dark(#ffffff, #1e1e1e);
color: light-dark(#1f2937, #f3f4f6);
border: 1px solid light-dark(#e5e7eb, rgba(255,255,255,0.1));
}
/* 3. Respect system preference */
@media (prefers-color-scheme: dark) {
:root:not(.theme-light) {
/* Dark mode tokens */
}
}
@media (prefers-color-scheme: light) {
:root:not(.theme-dark) {
/* Light mode tokens */
}
}
Theme Switching with JavaScript
// Theme manager with persistence
type Theme = 'light' | 'dark' | 'system';
function setTheme(theme: Theme) {
const root = document.documentElement;
// Remove existing theme classes
root.classList.remove('theme-light', 'theme-dark');
if (theme === 'system') {
// Let CSS media queries handle it
localStorage.removeItem('theme');
return;
}
// Apply explicit theme
root.classList.add(`theme-${theme}`);
localStorage.setItem('theme', theme);
}
function getSystemTheme(): 'light' | 'dark' {
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light';
}
// Initialize on page load (before render to prevent flash)
function initTheme() {
const saved = localStorage.getItem('theme') as Theme | null;
if (saved && saved !== 'system') {
document.documentElement.classList.add(`theme-${saved}`);
}
}
// Listen for system changes
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
// Only react if user hasn't set explicit preference
// CSS will handle via media queries
}
});
Preventing Flash of Wrong Theme (FOWT)
<!-- In <head>, before any CSS -->
<script>
(function() {
const theme = localStorage.getItem('theme');
if (theme === 'dark') {
document.documentElement.classList.add('theme-dark');
} else if (theme === 'light') {
document.documentElement.classList.add('theme-light');
}
})();
</script>
Worked Example: Weather/Sky/Ocean Atmospheric UI
This is the flagship example—a complete token system for a weather-inspired UI that adapts to time of day and atmospheric conditions.
Design Philosophy
The ocean and sky share a visual language:
- Dawn/Dusk: Warm gradients, soft transitions
- Midday: Bright, high contrast, clear
- Night: Deep blues, subtle glows, stars
- Storm: Dramatic grays, electric highlights
- Underwater: Teal depths, bioluminescent accents
Complete Token System
/* ══════════════════════════════════════════════════════════════════
OCEAN MODERN: ATMOSPHERIC UI TOKEN SYSTEM
A weather/sky/ocean-inspired design system with time-of-day awareness
══════════════════════════════════════════════════════════════════ */
:root {
/* ────────────────────────────────────────────────────────────────
PRIMITIVES: Atmospheric Color Palette
──────────────────────────────────────────────────────────────── */
/* Ocean Depths */
--ocean-surface: #38bdf8; /* Sunlit surface */
--ocean-shallow: #0ea5e9; /* Clear shallows */
--ocean-mid: #0284c7; /* Mid-depth */
--ocean-deep: #0369a1; /* Deep water */
--ocean-abyss: #075985; /* Abyssal zone */
--ocean-trench: #0c4a6e; /* Hadal zone */
/* Sky States */
--sky-dawn: #fef3c7; /* Golden hour */
--sky-morning: #bae6fd; /* Clear morning */
--sky-midday: #7dd3fc; /* Bright day */
--sky-golden: #fcd34d; /* Golden hour */
--sky-sunset: #fb923c; /* Sunset orange */
--sky-dusk: #a78bfa; /* Purple dusk */
--sky-twilight: #6366f1; /* Civil twilight */
--sky-night: #1e1b4b; /* Night sky */
/* Atmospheric Effects */
--atmosphere-haze: rgba(186, 230, 253, 0.3);
--atmosphere-fog: rgba(241, 245, 249, 0.6);
--atmosphere-mist: rgba(148, 163, 184, 0.4);
/* Storm System */
--storm-light: #9ca3af;
--storm-mid: #6b7280;
--storm-dark: #4b5563;
--storm-thunder: #374151;
--storm-lightning: #fbbf24;
/* Bioluminescence (dark mode accents) */
--bio-cyan: #22d3ee;
--bio-teal: #2dd4bf;
--bio-blue: #60a5fa;
--bio-purple: #a78bfa;
--bio-glow: rgba(34, 211, 238, 0.4);
/* Sand & Beach */
--sand-light: #fef3c7;
--sand-warm: #fde68a;
--sand-golden: #fcd34d;
--sand-wet: #d4a574;
/* Coral & Life */
--coral-pink: #fb7185;
--coral-orange: #fb923c;
--kelp-green: #22c55e;
--algae-teal: #14b8a6;
}
/* ════════════════════════════════════════════════════════════════════
SEMANTIC: Time-of-Day Themes
════════════════════════════════════════════════════════════════════ */
/* DAWN THEME (5am - 8am) - Warm, hopeful, transitional */
:root.atmosphere-dawn {
--color-text-primary: #1e293b;
--color-text-secondary: #475569;
--color-bg-primary: var(--sky-dawn);
--color-bg-secondary: #fef9e7;
--color-accent: var(--sky-golden);
--gradient-sky: linear-gradient(
180deg,
var(--sky-night) 0%,
var(--sky-dusk) 20%,
var(--sky-sunset) 40%,
var(--sky-golden) 70%,
var(--sky-dawn) 100%
);
--gradient-ocean: linear-gradient(
180deg,
var(--ocean-deep) 0%,
var(--ocean-mid) 50%,
var(--ocean-surface) 100%
);
}
/* DAYLIGHT THEME (8am - 5pm) - Bright, clear, energetic */
:root.atmosphere-day, :root.theme-light {
--color-text-primary: #0f172a;
--color-text-secondary: #334155;
--color-text-muted: #64748b;
--color-bg-primary: #ffffff;
--color-bg-secondary: #f8fafc;
--color-bg-elevated: #ffffff;
--color-accent: var(--ocean-shallow);
--color-accent-hover: var(--ocean-mid);
--gradient-sky: linear-gradient(
180deg,
var(--sky-midday) 0%,
var(--sky-morning) 50%,
#ffffff 100%
);
--gradient-ocean: linear-gradient(
180deg,
var(--ocean-abyss) 0%,
var(--ocean-deep) 30%,
var(--ocean-mid) 60%,
var(--ocean-shallow) 100%
);
/* Daylight uses shadows for elevation */
--elevation-method: shadow;
}
/* GOLDEN HOUR THEME (5pm - 7pm) - Warm, dramatic, nostalgic */
:root.atmosphere-golden {
--color-text-primary: #1c1917;
--color-text-secondary: #44403c;
--color-bg-primary: #fffbeb;
--color-bg-secondary: #fef3c7;
--color-accent: var(--sky-sunset);
--gradient-sky: linear-gradient(
180deg,
var(--sky-midday) 0%,
var(--sky-golden) 40%,
var(--sky-sunset) 70%,
var(--coral-pink) 100%
);
--gradient-ocean: linear-gradient(
180deg,
var(--ocean-deep) 0%,
#0891b2 50%,
#fcd34d 100%
);
}
/* TWILIGHT THEME (7pm - 9pm) - Transitional, mysterious */
:root.atmosphere-twilight {
--color-text-primary: #e2e8f0;
--color-text-secondary: #94a3b8;
--color-bg-primary: #0f172a;
--color-bg-secondary: #1e293b;
--color-bg-elevated: #334155;
--color-accent: var(--sky-twilight);
--gradient-sky: linear-gradient(
180deg,
var(--sky-night) 0%,
var(--sky-twilight) 30%,
var(--sky-dusk) 60%,
var(--sky-sunset) 100%
);
--gradient-ocean: linear-gradient(
180deg,
var(--ocean-trench) 0%,
var(--ocean-abyss) 50%,
var(--ocean-deep) 100%
);
}
/* NIGHT THEME (9pm - 5am) - Deep, calm, bioluminescent */
:root.atmosphere-night, :root.theme-dark {
--color-text-primary: #f1f5f9; /* 15.3:1 ✓ AAA */
--color-text-secondary: #cbd5e1; /* 9.3:1 ✓ AAA */
--color-text-muted: #94a3b8; /* 5.5:1 ✓ AA */
--color-bg-primary: #0c1222; /* Deep twilight navy */
--color-bg-secondary: #151b2e;
--color-bg-elevated: #1a1f3a;
--color-accent: var(--bio-cyan);
--color-accent-hover: var(--bio-teal);
--gradient-sky: linear-gradient(
180deg,
#020617 0%,
var(--sky-night) 50%,
#1e1b4b 100%
);
--gradient-ocean: linear-gradient(
180deg,
#020617 0%,
var(--ocean-trench) 50%,
var(--ocean-abyss) 100%
);
/* Night uses lighter surfaces for elevation */
--elevation-method: surface;
/* Bioluminescent glow effects */
--glow-accent: 0 0 20px var(--bio-glow);
--glow-subtle: 0 0 10px rgba(34, 211, 238, 0.2);
/* Surface elevation scale */
--surface-base: #0c1222;
--surface-1: #111827;
--surface-2: #1f2937;
--surface-3: #374151;
--surface-4: #4b5563;
}
/* STORM THEME - Dramatic, intense, electric */
:root.atmosphere-storm {
--color-text-primary: #f3f4f6;
--color-text-secondary: #d1d5db;
--color-bg-primary: var(--storm-thunder);
--color-bg-secondary: var(--storm-dark);
--color-bg-elevated: var(--storm-mid);
--color-accent: var(--storm-lightning);
--gradient-sky: linear-gradient(
180deg,
var(--storm-thunder) 0%,
var(--storm-dark) 30%,
var(--storm-mid) 60%,
var(--storm-light) 100%
);
--gradient-ocean: linear-gradient(
180deg,
#1f2937 0%,
#374151 40%,
#6b7280 80%,
#9ca3af 100%
);
/* Lightning flash animation */
--flash-color: rgba(251, 191, 36, 0.3);
}
/* ════════════════════════════════════════════════════════════════════
COMPONENT: Atmospheric UI Elements
════════════════════════════════════════════════════════════════════ */
/* Glass Card - works in all atmospheres */
.glass-card {
background: var(--glass-bg, rgba(255, 255, 255, 0.1));
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.2));
border-radius: 16px;
}
:root.theme-light .glass-card,
:root.atmosphere-day .glass-card,
:root.atmosphere-dawn .glass-card {
--glass-bg: rgba(255, 255, 255, 0.7);
--glass-border: rgba(0, 0, 0, 0.1);
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
}
:root.theme-dark .glass-card,
:root.atmosphere-night .glass-card,
:root.atmosphere-twilight .glass-card {
--glass-bg: rgba(15, 23, 42, 0.6);
--glass-border: rgba(255, 255, 255, 0.1);
box-shadow: var(--glow-subtle);
}
/* Wave Animation */
.wave-layer {
position: absolute;
bottom: 0;
left: 0;
width: 200%;
height: var(--wave-height, 100px);
background: var(--wave-color);
animation: wave var(--wave-duration, 8s) ease-in-out infinite;
opacity: var(--wave-opacity, 0.6);
}
@keyframes wave {
0%, 100% { transform: translateX(0) translateY(0); }
50% { transform: translateX(-25%) translateY(-10px); }
}
/* Bioluminescent Glow (dark mode only) */
:root.theme-dark .glow-element,
:root.atmosphere-night .glow-element {
box-shadow: var(--glow-accent);
transition: box-shadow 0.3s ease;
}
:root.theme-dark .glow-element:hover,
:root.atmosphere-night .glow-element:hover {
box-shadow: 0 0 30px var(--bio-glow), 0 0 60px rgba(34, 211, 238, 0.2);
}
/* Cloud Layer */
.cloud-layer {
position: absolute;
width: 100%;
height: 100%;
background-image: var(--cloud-pattern);
opacity: var(--cloud-opacity, 0.5);
animation: drift var(--cloud-speed, 60s) linear infinite;
}
@keyframes drift {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
Time-Based Theme Switching
type Atmosphere = 'dawn' | 'day' | 'golden' | 'twilight' | 'night' | 'storm';
function getAtmosphereFromTime(hour: number): Atmosphere {
if (hour >= 5 && hour < 8) return 'dawn';
if (hour >= 8 && hour < 17) return 'day';
if (hour >= 17 && hour < 19) return 'golden';
if (hour >= 19 && hour < 21) return 'twilight';
return 'night';
}
function setAtmosphere(atmosphere: Atmosphere) {
const root = document.documentElement;
// Remove all atmosphere classes
root.classList.remove(
'atmosphere-dawn', 'atmosphere-day', 'atmosphere-golden',
'atmosphere-twilight', 'atmosphere-night', 'atmosphere-storm',
'theme-light', 'theme-dark'
);
// Add new atmosphere
root.classList.add(`atmosphere-${atmosphere}`);
// Also set base theme for compatibility
const isDark = ['twilight', 'night', 'storm'].includes(atmosphere);
root.classList.add(isDark ? 'theme-dark' : 'theme-light');
}
// Auto-update based on time
function initAtmosphericUI() {
const updateAtmosphere = () => {
const hour = new Date().getHours();
setAtmosphere(getAtmosphereFromTime(hour));
};
updateAtmosphere();
// Update every 15 minutes
setInterval(updateAtmosphere, 15 * 60 * 1000);
}
Weather API Integration
interface WeatherCondition {
main: 'Clear' | 'Clouds' | 'Rain' | 'Thunderstorm' | 'Snow' | 'Mist';
description: string;
}
function getAtmosphereFromWeather(
weather: WeatherCondition,
hour: number
): Atmosphere {
// Storm conditions override time
if (weather.main === 'Thunderstorm') return 'storm';
// Heavy overcast dims everything
if (weather.main === 'Clouds' && weather.description.includes('overcast')) {
return hour >= 19 || hour < 6 ? 'night' : 'twilight';
}
// Default to time-based
return getAtmosphereFromTime(hour);
}
Anti-Patterns to Avoid
1. Pure Black Background (#000000)
Problem: Causes eye strain, harsh contrast, OLED "smearing" on scroll Solution: Use near-black like #0c1222, #121212, or #1a1a2e
2. Pure White Text (#FFFFFF) on Dark
Problem: Too harsh, causes halation for astigmatism users Solution: Use off-white like #f1f5f9, #e2e8f0
3. Same Colors for Both Themes
Problem: Teal that looks great on white becomes invisible on dark Solution: Use brighter variants in dark mode (ocean-400 instead of ocean-600)
4. Shadows in Dark Mode
Problem: Shadows disappear against dark backgrounds Solution: Use lighter surface colors for elevation instead
5. Inverted Light Mode Colors
Problem: Simply inverting creates jarring, unnatural results Solution: Design dark mode as its own coherent system
6. Ignoring System Preference
Problem: Forcing dark mode ignores user's system-wide preference
Solution: Default to prefers-color-scheme, allow override
7. Flash of Wrong Theme
Problem: Page loads light, then flashes to dark
Solution: Inline script in <head> before CSS loads
Testing Checklist
Visual Testing
- Primary text readable on all backgrounds (4.5:1+)
- Secondary text readable (4.5:1+)
- Muted text acceptable (3:1+ for large, 4.5:1+ for normal)
- Interactive elements distinguishable
- Focus states clearly visible
- Disabled states identifiable (but not required contrast)
- Elevation hierarchy clear without shadows
- No harsh white/black combinations
Functional Testing
- Theme toggle works correctly
- System preference respected on first load
- Theme persists across page reloads
- No flash of wrong theme
- Images adapt appropriately
- Code blocks readable
- Charts/graphs remain legible
- Form elements properly styled
Device Testing
- OLED screens (check for smearing on scroll)
- LCD screens (check for backlight bleed visibility)
- High brightness outdoor use
- Low brightness night use
- Color blindness simulation
Industry References
Material Design 3
- Base dark surface: #121212
- Tonal elevation with white overlay (5-11%)
- Primary colors at 80% lightness for dark mode
- 15.8:1 target contrast for elevated surfaces
Apple Human Interface Guidelines
- Respect system appearance setting
- Semantic colors that adapt automatically
- Increased vibrancy in dark mode
- Base system background: dynamic (not static black)
Figma
- Background: #2c2c2c (base), #383838 (elevated)
- Text: #ffffff (primary), #b3b3b3 (secondary)
- Accent: #0d99ff (brand blue, brightened for dark)
Discord
- Background: #36393f (main), #2f3136 (sidebar)
- Text: #dcddde (primary), #72767d (muted)
- Accent: #5865f2 (blurple, same in both modes)
Slack
- Background: #1a1d21 (base), #222529 (elevated)
- Uses colored sidebars in dark mode
- Maintains brand identity while adapting
Companion Skills
| Skill | Handoff Point |
|---|---|
color-contrast-auditor | After designing tokens, audit specific pairs |
design-system-creator | Integrate dark mode into broader design system |
web-design-expert | Overall visual direction and brand alignment |
color-theory-palette-harmony-expert | Generating initial color palettes |
Remember: Dark mode isn't the absence of light—it's the careful orchestration of luminance to guide attention, reduce strain, and create atmosphere.
FAQ
What does the dark-mode-design-expert skill do?
Master dark mode UI design with atmospheric theming, WCAG accessibility, and cross-platform best practices. Specializes in weather/sky/ocean-inspired color systems that adapt to time of day and environmental conditions.
How do I install dark-mode-design-expert?
Run npx skills add https://github.com/curiositech/some_claude_skills --skill dark-mode-design-expert in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/dark-mode-design-expert/ (personal) or .claude/skills/dark-mode-design-expert/ (project).
Which AI agents can use dark-mode-design-expert?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is dark-mode-design-expert safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains dark-mode-design-expert?
It is published by curiositech in curiositech/some_claude_skills. It has 304 recorded installs.
More from curiositech/some_claude_skills
video-processing-editing
curiositech/some_claude_skills
FFmpeg automation for cutting, trimming, concatenating videos. Audio mixing, timeline editing, transitions, effects. Export optimization for YouTube, social media. Subtitle handling, color grading, batch processing. Use for videogen projects, content creation, automated video production. Activate on "video editing", "FFmpeg", "trim video", "concatenate", "transitions", "export optimization". NOT for real-time video editing UI, 3D compositing, or motion graphics.
interior-design-expert
curiositech/some_claude_skills
Expert interior designer with deep knowledge of space planning, color theory (Munsell, NCS), lighting design (IES standards), furniture proportions, and AI-assisted visualization. Use for room layout optimization, lighting calculations, color palette selection for interiors, furniture placement, style consultation. Activate on "interior design", "room layout", "lighting design", "furniture placement", "space planning", "Munsell color". NOT for exterior/landscape design, architectural structure, web/UI design (use web-design-expert), brand color theory (use color-theory-palette-harmony-expert), or building codes/permits.
cv-creator
curiositech/some_claude_skills
Professional CV and resume builder transforming career narratives into ATS-optimized, multi-format resumes. Integrates with career-biographer for data and competitive-cartographer for positioning. Generates PDF, DOCX, LaTeX, JSON Resume, HTML, and Markdown. Activate on 'resume', 'CV', 'ATS optimization', 'job application'. NOT for cover letters, portfolio websites (use web-design-expert), LinkedIn optimization, or interview preparation.
personal-finance-coach
curiositech/some_claude_skills
Expert personal finance coach with deep knowledge of tax optimization, investment theory (MPT, factor investing), retirement mathematics (Trinity Study, SWR research), and wealth-building strategies grounded in academic research. Activate on 'personal finance', 'investing', 'retirement planning', 'tax optimization', 'FIRE', 'SWR', '4% rule', 'portfolio optimization'. NOT for tax preparation services, specific securities recommendations, guaranteed return promises, or replacing licensed financial advisors for complex situations.
photo-composition-critic
curiositech/some_claude_skills
Expert photography composition critic grounded in graduate-level visual aesthetics education, computational aesthetics research (AVA, NIMA, LAION-Aesthetics, VisualQuality-R1), and professional image analysis with custom tooling. Use for image quality assessment, composition analysis, aesthetic scoring, photo critique. Activate on "photo critique", "composition analysis", "image aesthetics", "NIMA", "AVA dataset", "visual quality". NOT for photo editing/retouching (use native-app-designer), generating images (use Stability AI directly), or basic image processing (use clip-aware-embeddings).
pwa-expert
curiositech/some_claude_skills
Progressive Web App development with Service Workers, offline support, and app-like behavior. Use for caching strategies, install prompts, push notifications, background sync. Activate on "PWA", "Service Worker", "offline", "install prompt", "beforeinstallprompt", "manifest.json", "workbox", "cache-first". NOT for native app development (use React Native), general web performance (use performance docs), or server-side rendering.
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.