Dark mode isn’t just “invert the colors.” Done poorly, it’s harsh and hard to read. Done well, it feels natural and reduces eye strain.
The principles
A few things I’ve learned from building dark interfaces:
Don’t use pure black
#000000 on screens creates too much contrast with white text. Instead, use a very dark teal — something like #091c1e — which is easier on the eyes while still feeling deep and immersive.
Reduce contrast for body text
White text (#ffffff) on a dark background is jarring. Aim for an off-white like #f6fff5 for headings, and use reduced opacity for body text:
| Role | Color | Hex |
|---|---|---|
| Headings | Near white | #f6fff5 |
| Body | 80% opacity | rgba(246,255,245,0.8) |
| Muted | Warm gray | #978e81 |
Use warm accents
In dark interfaces, warm accent colors feel more natural than cold ones. An orange like #f6833b creates energy without overwhelming the reading experience.
The technical bits
CSS custom properties make theming straightforward:
:root {
--background: #091c1e;
--foreground: #f6fff5;
--accent: #f6833b;
}
This keeps your design tokens in one place. Change a variable, and the entire site updates.
Typography matters most
In dark mode, font rendering behaves differently. Lighter text on dark backgrounds appears thicker due to subpixel antialiasing. Counter this with:
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
This produces thinner, crisper text that reads much better on dark surfaces.