Neutrals Do the Heavy Lifting: Choosing Grays for Interfaces
Designers obsess over the accent color and ignore the ninety percent of the screen that is gray. That ratio is exactly backwards.
Dark mode is not inverted light mode. Learn why pure black and pure white fail, how to derive a dark surface scale, and a step-by-step method for palettes that switch themes cleanly.
Dark mode started as a novelty and is now an expectation. Your operating system has it, your users toggle it, and reviewers notice when it looks like an afterthought. The problem is that most dark themes are an afterthought: someone takes the light palette, flips the whites to blacks, and ships it. The result looks fine in a screenshot and awful in use.
This guide explains why naive inversion fails, and gives you a method for a dark theme that feels designed rather than generated.
Three physical and perceptual facts make inversion a bad default.
Pure white on pure black is harsh. #FFFFFF text on #000000 produces maximum contrast, which sounds good until you use it for a paragraph. The halation — the glow that blooms around bright text on dark backgrounds — makes long reads tiring and can physically smear on OLED screens. Real dark interfaces avoid full extremes.
Lightness is not perceived linearly. A gray that looks "mid" between black and white in code is not mid in perception, because the eye is far more sensitive to differences in dark tones than in light ones. If you translate every light-surface color to its numerical inverse, the resulting steps between surfaces will look uneven.
Shadows and depth change meaning. In light mode, depth usually comes from shadows and subtle borders. In dark mode, shadows almost disappear, so depth has to be carried by lighter surfaces — a raised card is lighter, not shadowed. Inverting colors doesn't change this logic, so inverted palettes lose their sense of layering.
The most reliable way to design a dark theme is to build it from a surface ramp rather than from a text color. Define a small family of dark backgrounds that step apart clearly, then place text on top.
A practical dark surface set:
#121212–#0F1115 — not pure black; slightly raised above the darkest possible value.#1E1E1E–#1B1F27 — visibly lighter than the base.#2A2A2A–#282D38 — lighter again.The rule of thumb from Material Design is elegant: the higher an element floats, the lighter its surface becomes. This replaces the shadow-based depth of light mode with a "lightness elevation" system that reads correctly on dark backgrounds.
Set the base slightly above #000000 for two reasons: it reduces harsh halation, and it leaves room for a true-black layer (for OLED battery saving or full-bleed media) to sit below the base when you need it.
Once your surfaces are set, choose text deliberately:
#E6E6E6–#EAEAEA, or up to about 87% white. Full white is reserved for the highest-emphasis elements only.Because the eye is sensitive in dark ranges, small lightness adjustments make a big visual difference. Test secondary and disabled text against the actual surface they sit on, not against pure black, since a lighter card raises the effective background and can drop your contrast below 4.5:1.
Accents behave differently on dark backgrounds. A saturated blue that looks rich on white can vibrate or glow unpleasantly on near-black, and a dark accent that reads well on white can disappear entirely on a dark surface.
Two adjustments usually fix it:
A useful pattern is to define each accent as a pair: an accent for light surfaces and an accent-on-dark for dark surfaces, rather than a single value reused in both.
Here's a workflow that produces a coherent dark theme instead of an inverted one:
Two mistakes dominate dark-mode QA.
The first is testing only the default state. Dark themes often break in states: a hover color that was darkened for light mode becomes invisible, a disabled button loses its boundary, a toast's shadow vanishes and it appears to have no edge. Walk through hover, focus, active, disabled, error, and empty states in both themes.
The second is trusting the design tool. Simulated dark mode in a design app is not the same as the rendered result under a real display's gamma curve. Ship to a device and look.
And whatever you do, keep the contrast standards: 4.5:1 for body text, 3:1 for large text and meaningful UI boundaries, in both themes. Dark mode is not an exemption from accessibility — it's a second chance to get it wrong if you're careless.
Usually no for large surfaces. Slightly raised values like #121212 reduce eye strain and halation, and preserve room for a true-black layer where you need it (like OLED media backgrounds). Many OLED-focused apps do offer a true-black option, but as a choice rather than the default.
That's halation — bright text blooming against a dark background, most noticeable on OLED. Reduce it by lowering your white to around 87% and avoiding full #FFFFFF for body copy.
Often yes. A single accent frequently fails on one of the two themes because it's too dark for dark surfaces or too light for light ones. Defining an accent and an accent-on-dark pair keeps both themes legible while preserving the brand hue.
You can seed it automatically, but review it manually. Automatic inversion gets the surfaces roughly right and almost always gets accents, borders, and elevation wrong. Treat any automated dark palette as a first draft.
Start by generating a coordinated set in the palette generator, then drop the values into the UI color playground to see how they behave on real components in both modes. When you're happy, push the token set through the palette exporter so your light and dark themes stay in sync.
Founder & Developer of Color Palette — Sagar Chachapara is an independent developer who builds color tools and writes about color theory, accessible design, and working with palettes in the browser.
sagarchachapara1997@gmail.comTry the techniques from this guide in our free tools — no sign-up required.
More in Web Design · All articles · FAQ
Designers obsess over the accent color and ignore the ninety percent of the screen that is gray. That ratio is exactly backwards.
The difference between a gradient that feels modern and one that feels dated comes down to restraint, color harmony, and where you place it.
Constraint is not a limitation, it is a design tool. The palettes that look most considered are usually the smallest ones.