Skip to content
All posts
DesignCSSAccessibilityTailwind CSS

Dark mode that doesn't hurt

Good dark themes aren't white themes with the colors flipped. Contrast, desaturation, and elevation done right.

KSKavin SmithJune 2, 20262 min read

A bad dark mode is a white site with the brightness inverted: pure #000 backgrounds, pure #fff text, and neon accents that scream at you. A good dark mode is a different design, tuned for a dim room.

Rule 1: Never pure black

Pure black next to pure white text is a contrast ratio of 21:1 — technically "accessible", practically uncomfortable. It causes halation on OLED screens and makes everything shimmer.

Use a very dark gray instead:

SurfaceValue
Page background#0a0a0a → use #08080a
Raised cards#101014
Bordersrgba(255,255,255,0.08)

Elevation in dark mode comes from lifting surfaces with lighter grays, not shadows.

Rule 2: Desaturate your accents

A #7c3aed purple on white feels calm. The same purple on near-black can feel like a laser. Knock the saturation down or bump the lightness a notch in dark mode — keep the hue, soften the volume.

Rule 3: Respect prefers-color-scheme, offer a choice

Default to the user's system setting, but let them override it. And store the choice so it survives a reload:

<ThemeProvider attribute="class" defaultTheme="system" enableSystem />

Rule 4: Don't flash

The classic dark-mode bug: the page loads light, then snaps dark. Prevent the flash-of-wrong-theme by setting the class on <html> before first paint — a small inline script or a provider that does it for you.

A quick checklist

  • Backgrounds are dark grays, not #000
  • Text is off-white, not #fff
  • Focus rings are clearly visible in both themes
  • Images and shadows don't look broken in dark mode
  • The toggle survives page loads

Dark mode is table stakes now. Do it properly and it's invisible; do it lazily and it's the first thing people complain about.