UX & UI

Designing for Dark Mode: A Practical Guide

Dark mode done right: why it matters, true black vs dark grey, WCAG contrast, elevation with surfaces, desaturating color, handling images, and CSS implementation.

// DD EditorialJun 13, 20269 min read

Dark mode is no longer a novelty toggle; it’s an expectation. Operating systems ship with it, users set it system-wide, and many spend hours a day in dark interfaces. But a good dark theme is not just an inverted light one. Flipping black and white produces eye-searing text, muddy colors, and broken depth. This guide covers the decisions that separate a thoughtful dark mode from a lazy one.

Why Dark Mode Matters

Dark mode earns its place for a few concrete reasons rather than pure fashion.

  • Comfort in low light. A bright screen in a dark room is fatiguing. A darker UI reduces that glare and feels easier on the eyes at night.
  • User preference and control. Many people simply prefer it, and respecting a system-level choice signals a polished, considerate product.
  • Battery on OLED screens. On OLED and AMOLED displays, dark pixels draw less power, so a genuinely dark theme can extend battery life.

What dark mode is not is a guaranteed accessibility win. For some users, especially those with astigmatism, light text on a dark background can blur (“halation”). The right move is to offer both modes and respect the user’s choice, not to declare one universally better.

True Black vs Dark Grey

The first real decision is your base background color, and the instinct to use pure black (#000000) is usually wrong.

Pure black against pure white text creates extreme contrast that can cause eye strain and a smeary halation effect, particularly for body text. It also leaves you nowhere to go when you need to show depth, since you can’t make a surface darker than black.

A dark grey base, somewhere around #121212, is the common recommendation (it’s the value Material Design uses) precisely because it solves both problems. It’s still clearly dark, but it gives you room to build lighter surfaces on top and softens the contrast with text.

Reach for true black only when you have a deliberate reason, such as an OLED battery focus or a specific aesthetic, and even then, test it carefully against real content.

Contrast and WCAG

Dark mode does not exempt you from contrast standards. The WCAG minimums still apply: a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text and meaningful UI components against their background.

The twist is that you can have too much contrast. Pure white text (#FFFFFF) on a dark grey background is so high-contrast it vibrates and tires the eyes. The fix is to soften your “white”:

  • Use an off-white like #E0E0E0 or #DEDEDE for primary text instead of pure white.
  • Use progressively lower-opacity whites or greys for secondary and disabled text to establish hierarchy.
  • Always verify the result still clears 4.5:1 with a contrast checker; softening text must not push it below the minimum.

Hierarchy in dark mode is built largely through text emphasis levels, so getting these opacity steps right matters a great deal.

Elevation Through Surfaces

In light mode, elevation is shown with shadows: a raised card casts a darker shadow on the surface below. In dark mode, shadows barely register against a dark background, so that cue mostly disappears.

The dark-mode solution is to express elevation with lightness instead. The higher a surface sits, the lighter it gets. A background might be #121212, a card on top of it a slightly lighter grey, a dialog above that lighter still. This creates a believable sense of depth without relying on invisible shadows.

  • Define a small set of surface levels, each a step lighter than the last.
  • Apply them consistently: the same component type should sit at the same elevation everywhere.
  • Keep the steps subtle. Big jumps in lightness read as separate colors, not layers.

Desaturating Colors

Brand colors that look great on white often turn aggressive on dark backgrounds. Highly saturated hues vibrate against dark surfaces and can fail contrast or simply hurt to look at.

The fix is to desaturate and lighten your accent colors for dark mode. A bold, deep brand blue may need to become a softer, lighter, less saturated blue to sit comfortably and stay legible. Many design systems maintain a separate set of color tokens for dark mode for exactly this reason.

Practical rules:

  • Avoid fully saturated colors on dark backgrounds; pull saturation down.
  • Lighten accent colors so they have enough contrast against the dark surface.
  • Test every accent color used for text or icons against its actual background for the 4.5:1 / 3:1 thresholds.

Images, Shadows, and Other Details

A few content types need special handling when the lights go down.

  • Images. Photos generally survive, but bright white image backgrounds become glaring rectangles. Logos and illustrations with white or transparent backgrounds may need dark-mode variants. Consider a subtle dimming or a slight border to ease the transition.
  • Shadows. Since shadows are weak on dark surfaces, lean on elevation-by-lightness instead. Where you do use shadows, they can be deeper and softer to add a hint of depth.
  • Borders and dividers. Hairline borders can vanish; use a low-opacity light color to keep separation visible.
  • Charts and data viz. Re-tune palettes so series stay distinguishable against the dark canvas, and avoid pure white gridlines that scream for attention.

Implementation With CSS

Modern CSS makes dark mode straightforward to ship. The prefers-color-scheme media query reads the user’s operating-system preference, and CSS custom properties let you swap an entire palette in one place.

The cleanest pattern is to define your colors as variables for the default (light) theme, then override those same variables inside a dark-mode block:

:root { --bg: #ffffff; --text: #1a1a1a; } @media (prefers-color-scheme: dark) { :root { --bg: #121212; --text: #e0e0e0; } }

Every component then references var(--bg) and var(--text) rather than hard-coded colors, so the whole UI shifts automatically. A few additional notes:

  • Add color-scheme: light dark; so native controls (form fields, scrollbars) adapt too.
  • If you offer a manual toggle, layer a class or data-theme attribute over the media query so users can override the system default, and persist their choice.
  • Avoid a flash of the wrong theme on load by applying the saved preference before first paint.

The takeaway

A great dark mode is designed, not inverted. Start from a dark grey base rather than pure black, soften white text to a comfortable off-white while still clearing WCAG contrast, and build depth through lighter surfaces instead of shadows. Desaturate your accent colors, handle images and borders deliberately, and implement it cleanly with CSS custom properties driven by prefers-color-scheme. Offer both themes, respect the user’s choice, and test against real content, that’s what turns dark mode from a gimmick into a genuinely better experience.

DD Editorial
DD Editorial
// DesignerDiscussion editorial team

We test tools, read the docs so you don't have to, and rank the agencies actually shipping great work.

  dd@signal:~ — subscribe.sh
$ ./join --weekly-signal
> one email a week. design intel, dev drops, agency rankings. zero noise.