A polished dark mode design system workspace with layered dark surfaces, token strips, contrast cards, semantic color swatches, focus ring samples, and light and dark theme panels.

Color guide

Dark mode color guide

Dark mode is not a light palette with the values inverted. A strong dark theme uses deliberate surfaces, readable foregrounds, restrained chroma, visible borders, accessible focus states, tuned semantic colors, and CSS that respects user preferences.

Short answer

Build dark mode as its own color system. Start with a near-black surface ladder, then define readable foregrounds, muted text, borders, focus rings, action colors, semantic states, chart colors, and theme roles. Check every real foreground and background pair in dark mode, reduce chroma for large areas, avoid color-only meaning, and document reusable color roles where appropriate.

  • Dark mode should not be made by simply inverting light mode. Inversion usually breaks hierarchy, brand color, semantic states, images, shadows, and comfort.
  • Use several dark surfaces, not one flat background. Page, panel, raised, hover, selected, and overlay surfaces need separate roles.
  • Contrast still matters in dark mode, but visual comfort also matters. Pure white on pure black can feel harsh in dense interfaces.
  • Highly saturated colors can glow or vibrate on dark surfaces. Reduce chroma for large areas and reserve vivid color for clear actions and states.
  • Semantic colors need dark-mode-specific tuning. Success, warning, error, info, selected, disabled, and focus colors should be tested independently.
  • CSS can respect user preference with prefers-color-scheme and can signal native control rendering with color-scheme.

What dark mode color design is

Dark mode color design is the practice of building a complete interface palette for dark backgrounds. It includes page backgrounds, surfaces, raised panels, text, muted text, borders, dividers, icons, focus indicators, links, buttons, form controls, semantic states, charts, shadows, images, and theme tokens.

A dark theme is successful when it feels comfortable in low-light conditions, preserves hierarchy, remains readable, supports the brand, respects user preferences, and stays accessible. It should feel like the same product in a different lighting condition, not a separate product with a decorative black skin.

Dark mode color system

A dark mode color system is a set of role-based colors, contrast rules, and semantic states designed specifically for dark user interface contexts.

Diagram showing a dark mode color system built from surface roles, foreground roles, accents, semantic states, accessibility checks, and theme tokens.
Dark mode becomes reliable when it is built from roles: surfaces, foregrounds, accents, states, verification, and theme tokens.

Why inversion is not enough

Automatic inversion can produce a first draft, but it rarely produces a polished dark theme. A light interface often relies on subtle gray borders, dark shadows, pale backgrounds, high-chroma accents, and brand colors chosen for white surfaces. When those values are flipped, hierarchy and meaning can collapse.

Inversion also affects images, logos, charts, disabled states, shadows, focus rings, code blocks, maps, illustrations, and semantic colors. A red error value that works on white may become too loud on charcoal. A pale blue focus ring may disappear on a tinted dark panel. A brand yellow may fail as button text or glow against a near-black background.

Why dark mode needs its own palette decisions.
Light-mode assumption Dark-mode problem Better move
White page, gray card Cards may vanish if all surfaces become similar dark grays Create a surface ladder with clear role steps
Black text Pure white replacement can glare in long reading contexts Use near-white primary text and tuned muted text
Soft gray border Border may disappear on dark panels Use visible border tokens checked against adjacent surfaces
Bright brand accent Accent may glow or dominate dense UI Reduce chroma or use the vivid value only for small roles
Drop shadow elevation Shadow can be invisible on dark backgrounds Use surface lightness, borders, and subtle glow instead
Red, green, yellow states States can become harsh or ambiguous Tune semantic palettes separately for dark mode

Start with a surface ladder

The surface ladder is the foundation of dark mode. It defines the difference between the page background, base panels, raised cards, controls, hover states, selected states, overlays, modals, and tooltips. Without it, a dark interface becomes a flat field of nearly identical rectangles.

A common approach is to use near-black for the page, then slightly lighter or cooler surfaces for panels and raised elements. The steps should be visible enough to support scanning, but subtle enough that the interface still feels calm. In dense software, the surface ladder often matters more than the accent color.

Page background

The deepest stable surface. Near-black is often easier to work with than absolute black because it leaves room for shadows, borders, and hierarchy.

Base surface

The default card, panel, input, or sidebar surface. It should separate from the page without creating a high-contrast patchwork.

Raised surface

A slightly lighter or clearer surface used for menus, popovers, modals, active panels, and elements that sit above the page.

Interactive surface

Hover, pressed, selected, and active states need their own values so controls do not rely only on a border or shadow.

Recommended dark surface roles

Exact values depend on brand, product density, display quality, and desired mood, but the role structure is consistent. Name surfaces by use rather than by literal color so they can adapt across light, dark, high contrast, and future themes.

Core dark-mode surface roles to define.
Role Purpose What to check
surface-page Main page or app background Comfort, glare, and enough contrast for panels
surface-base Cards, panels, sidebars, and input wells Separation from page background
surface-raised Menus, dialogs, popovers, and active sheets Visible elevation without heavy shadows
surface-hover Hover states for controls and rows Clear enough for mouse users without flicker
surface-selected Selected tabs, rows, pills, and nav items Meaning is clear with text or icon cues
surface-overlay Scrims, drawers, modals, and temporary layers Background relationship and readable foregrounds
border-subtle Low-emphasis dividers and control edges Visible against both neighboring surfaces
border-strong High-emphasis component boundaries Non-text contrast and clear affordance

Tune text for readability and comfort

Readable text is the most important dark-mode color decision. WCAG contrast thresholds still apply, but a dense interface can technically pass while feeling harsh if every paragraph uses pure white on pure black. Many mature dark themes use near-white primary text, softer secondary text, and carefully tested muted text.

Avoid making muted text so quiet that it becomes decorative. Labels, metadata, helper text, placeholders, disabled text, captions, breadcrumbs, tab labels, timestamps, and chart labels all need to be readable enough for their job.

Dark-mode foreground roles.
Role Use Dark-mode guidance
text-primary Body copy, headings, primary labels Near-white, not necessarily pure white
text-secondary Supporting labels and descriptions Softer than primary but still comfortably readable
text-muted Metadata, timestamps, inactive labels Use sparingly and test against every surface
text-disabled Unavailable controls Must communicate disabled state without vanishing
text-on-accent Text on buttons, chips, alerts, and badges Check against each accent and state color
icon-primary Functional icons Treat icons as foregrounds, not decoration

Contrast in dark mode

Contrast is not optional in dark mode. Text, icons, buttons, input boundaries, focus indicators, chart marks, and status components need enough contrast against the surface where they actually appear. Do not check a token only against the page background if it will be used on cards, tinted panels, gradients, or images.

Dark themes also need real-state testing. The normal state might pass, while hover, active, disabled, selected, loading, error, warning, and focus states fail. This is common when teams lower contrast to make the interface feel softer.

  • Check primary text, secondary text, muted text, and disabled text on every surface role.
  • Check button text on primary, secondary, danger, warning, success, and ghost button backgrounds.
  • Check links, focus rings, input borders, selected rows, checkboxes, radio buttons, toggles, and slider handles.
  • Check chart labels, legends, gridlines, map labels, and data marks separately from normal UI text.
  • Check overlays, drawers, modal scrims, skeleton loaders, and toast notifications.

Control chroma and saturation

A color that feels balanced on white can feel electric on a dark surface. This is why dark mode often needs lower chroma for large fills, softer tints for backgrounds, and separate accent values for text, borders, and filled controls.

Use vivid colors intentionally. A saturated blue focus ring, red danger button, or green success dot can be useful because it attracts attention. The problem starts when large panels, backgrounds, charts, and decorative blocks use the same vivid color for too much area.

Large areas

Reduce chroma and keep lightness controlled. Large saturated regions can feel noisy and fatiguing on dark backgrounds.

Small accents

Small interactive accents can carry more saturation because they need to be found quickly.

Semantic states

Use separate dark-mode ramps for error, warning, success, and info so each state remains legible and distinct.

Chart palettes

Reduce saturation where the chart is dense. Preserve distinguishability with labels, markers, and ordering.

Use perceptual color spaces when possible

Simple hex edits and HSL lightness changes can create uneven steps in dark palettes. A color ramp may look balanced in code but jump visually from one step to the next. Perceptual color spaces such as Lab, LCH, OKLab, and OKLCH can make dark-mode ramps more predictable because they are designed around how color differences are perceived.

You do not need every production token to be authored by hand in OKLCH, but it is useful for palette creation. Build candidate ramps with more even perceived lightness and chroma, then test the actual rendered colors in browsers and design tools.

Color model considerations for dark mode.
Model Useful for Caution
HEX and RGB Final CSS values and exact handoff Hard to adjust perceptually by eye
HSL Simple hue, saturation, and lightness thinking Lightness steps may not look visually even
Lab and LCH Perceptual color adjustments and ramps Needs gamut checking for output colors
OKLab and OKLCH More predictable modern ramps and theme tokens Still needs browser and contrast testing

Semantic colors need separate dark-mode ramps

Success, warning, error, danger, info, selected, new, promoted, disabled, and destructive colors often fail when reused from light mode. Dark mode changes the perceived brightness and urgency of those colors, so each semantic family needs its own foreground, background, border, icon, and filled-control values.

This is especially important for errors and warnings. A pale red error background may vanish on a dark card, while a saturated red panel may feel alarming in a context that only needs mild correction. Tune severity through role and scale, not hue alone.

Semantic roles to test in dark mode.
State Roles needed Check
Success Text, icon, border, soft background, filled background Distinguishable from brand green and chart green
Warning Text, icon, border, soft background, filled background Readable without relying only on yellow
Error Text, icon, border, soft background, filled background Clear but not painfully saturated
Info Text, icon, border, soft background, filled background Distinct from primary action color
Selected Background, text, icon, border, focus relationship Visible in lists, tabs, tables, and nav
Disabled Foreground, background, border, cursor and label cues Unavailable but still understandable

Focus rings and keyboard states

Dark mode often exposes weak focus styling. A focus ring that is visible on white may disappear on charcoal, tinted cards, image backgrounds, or saturated buttons. Keyboard users need a clear focus indicator on every interactive element.

Use a focus token that has strong contrast against the component and the surrounding surface. If one ring color cannot work everywhere, use a layered focus style: an inner ring, an outer ring, offset, outline, or shadow that adapts by component role.

  • Check focus on dark page backgrounds, raised cards, tinted panels, primary buttons, danger buttons, disabled-adjacent controls, and image overlays.
  • Do not rely only on a subtle glow. Make the active focus boundary geometrically clear.
  • Ensure hover, focus, active, and selected states are visually different from each other.
  • Test keyboard order and focus visibility together. A beautiful ring is not enough if it is clipped by overflow.

Borders, dividers, and elevation

Light themes often use shadows for elevation. Dark themes can use shadows too, but a black shadow on a near-black background may be invisible. The more reliable dark-mode elevation toolkit is surface lightness, border contrast, subtle glow, spacing, and layer order.

Borders deserve explicit tokens. A border that is perfect on surface-base may disappear on surface-raised or become too loud on surface-page. High-density dashboards, tables, code editors, forms, and settings screens need particularly careful divider tuning.

Subtle borders

Use for low-emphasis separators, table rows, and card outlines. They should support structure without drawing too much attention.

Strong borders

Use for inputs, focus-adjacent controls, selected states, and important layout boundaries.

Elevation surfaces

Use slightly lighter surfaces for popovers, menus, dialogs, and active sheets when shadows are not enough.

Glow carefully

A soft color glow can help focus or active states, but it should not replace a clear boundary.

Forms and native controls

Forms are where dark mode often breaks. Inputs, selects, textareas, checkboxes, radio buttons, sliders, toggles, validation messages, placeholders, autofill states, and disabled states all need real dark-mode values.

CSS color-scheme can also affect native form controls, scrollbars, and built-in UI colors. If a page supports dark mode, declare the intended color schemes so the browser can render supported native controls appropriately. Then still test the actual controls in target browsers.

Dark-mode form color checks.
Form part What can fail Better practice
Input background Too close to page or card surface Use a defined input surface token
Input border Invisible when inactive or too loud when active Separate default, hover, focus, and error borders
Placeholder text Too faint to read or too strong to distinguish from input text Give placeholder a readable but clearly secondary token
Validation Error color only appears in border Add text, icon, and field-level message
Autofill Browser color clashes with dark theme Test real browser autofill behavior
Scrollbar and controls Native UI stays light or low contrast Use color-scheme and browser testing

Images, logos, and illustrations

Dark mode is not only CSS colors. Images, logos, icons, screenshots, illustrations, maps, and product photography may need separate assets or treatment. A logo built for white backgrounds may need a reversed version. A screenshot with a white UI can create a bright block inside an otherwise comfortable dark page.

Do not dim every image automatically. Dimming can reduce clarity, distort brand colors, and make people look unnatural. Instead, decide by asset type: transparent logos, UI screenshots, editorial images, decorative illustrations, and data visuals each need different rules.

  • Provide full-color, one-color, and reversed logo variants.
  • Test transparent PNG and SVG marks on every dark surface where they appear.
  • Use dark-mode screenshot variants when the surrounding page is dark.
  • Add subtle borders or containers around light images so they do not feel pasted onto the page.
  • Avoid applying a global opacity filter to meaningful images, charts, or product photos.

Charts and data in dark mode

Charts need special attention because dark mode changes how gridlines, labels, legends, data marks, and categorical colors are perceived. A palette that is distinguishable on white can become muddy on charcoal, while a high-saturation chart can feel noisy in a dark dashboard.

Use lighter labels, quieter gridlines, sufficient mark contrast, and direct labeling where possible. Sequential scales, diverging scales, and categorical palettes should be tuned for the actual chart background rather than copied from the light theme.

Gridlines

Keep gridlines visible enough to read the chart but quiet enough that they do not compete with the data.

Labels

Axis labels, legends, and tooltips need their own foreground and surface tokens.

Categorical colors

Make categories distinguishable in dark mode and under color-vision simulations.

Alerts in data

Risk, loss, error, and warning colors should include labels or symbols, not only hue.

CSS support for dark mode

Modern CSS gives teams several ways to implement dark mode. The prefers-color-scheme media feature can respond to the user preference. The color-scheme property tells the browser which schemes an element supports, which can affect built-in rendering such as controls and scrollbars. CSS custom properties can hold theme tokens. light-dark() can choose between two colors when the used color scheme is known.

The most maintainable approach is usually token-first. Define semantic tokens such as --color-surface-page, --color-text-primary, --color-border-subtle, --color-action-primary, and --color-status-danger. Then assign different values for light and dark contexts. Components should consume tokens, not hard-code one-off dark values.

CSS features that support theme-aware color.
Feature What it does Dark-mode use
prefers-color-scheme Detects whether the user has expressed a light or dark preference Apply dark token values when the user prefers dark
color-scheme Indicates supported color schemes for browser-rendered UI Help form controls and scrollbars match the theme
CSS custom properties Store reusable theme values Map component roles to light and dark values
light-dark() Selects between light and dark color values in a color-scheme context Useful for paired values without duplicating every declaration
forced-colors Detects forced color mode Avoid fighting user-selected high-contrast colors

Respect user preference without trapping users

Dark mode should usually respect the system preference by default, but many products also need an explicit theme setting. A user may prefer dark mode at night, light mode in bright environments, or a specific theme for accessibility reasons. A good theme system can support system, light, dark, and sometimes high-contrast modes.

If the product includes a manual setting, make the choice persistent and easy to change. Avoid theme switches that flash through the wrong theme on page load. This is often solved by setting an early class or data attribute before the main CSS renders.

  • Provide system, light, and dark options when the app has persistent user accounts or long sessions.
  • Avoid hiding the theme setting deep inside account preferences for products used at night or for long reading sessions.
  • Persist the chosen theme without causing a flash of the wrong theme.
  • Do not override forced-colors or high-contrast user settings unless there is a tested reason.

Dark mode and accessibility beyond contrast

Dark mode accessibility is broader than a contrast number. People use dark themes for comfort, migraine sensitivity, low-light reading, battery preference, visual focus, and personal taste. Others find dark themes harder to read, especially with thin type, astigmatism, bright accents, or low-quality displays.

This means dark mode should be optional when possible and tested across real content densities. Long-form reading, dense tables, code editors, dashboards, forms, map views, and marketing pages each create different accessibility risks.

Accessibility risks to test in dark mode.
Risk Where it appears Mitigation
Glare or halation Pure white text on pure black, thin type, high-brightness screens Use near-white text and comfortable font weight
Lost structure Subtle borders, table rows, cards, nested panels Create visible surface and border tokens
Color-only meaning Alerts, charts, required fields, links, status dots Add text, icons, patterns, labels, or shape
Invisible focus Buttons, menus, form controls, dark tinted panels Use high-contrast focus rings with geometry
Over-saturated accents Charts, buttons, badges, notifications, gradients Reduce chroma for large areas and tune semantic ramps
Forced colors conflict Custom controls, SVG icons, pseudo-elements Test forced-colors and avoid hard-coded overrides

A practical dark-mode workflow

A reliable workflow starts with roles, not colors. If the team starts by choosing a charcoal background and a blue accent, the system will quickly run into missing states. Instead, list the UI roles, assign candidate values, test them in real components, and adjust in context.

  • Inventory every color role in the light theme: surfaces, text, borders, actions, semantic states, charts, focus, overlays, and media assets.
  • Create dark-mode surface roles first, including page, base, raised, hover, selected, overlay, and input surfaces.
  • Define text and icon roles for primary, secondary, muted, disabled, inverse, and on-accent foregrounds.
  • Tune brand accents and semantic colors separately for dark backgrounds.
  • Build sample screens with real content density, not only isolated swatches.
  • Check contrast for text, icons, borders, focus rings, controls, and chart elements.
  • Test light mode, dark mode, system preference, forced-colors or high-contrast modes where relevant, and real device brightness.
  • Document the final values as tokens and include usage rules for components.

Dark-mode token structure

Tokens keep dark mode maintainable. Avoid naming tokens after their current appearance, such as dark-gray-2, when the token actually means a card surface or muted text. Role names make it possible to change values without rewriting components.

Useful token groups for dark mode.
Token group Example roles Why it matters
Surface surface-page, surface-base, surface-raised, surface-overlay Keeps hierarchy separate from brand color
Foreground text-primary, text-secondary, text-muted, text-disabled Prevents unreadable muted and disabled states
Border border-subtle, border-strong, border-focus Makes structure and affordance testable
Action action-primary, action-hover, action-active, action-disabled Keeps buttons and links consistent
Semantic status-success, status-warning, status-danger, status-info Gives states tuned values for dark backgrounds
Data chart-series, chart-grid, chart-label, chart-highlight Avoids copying light-mode chart colors blindly
Overlay scrim, modal-surface, tooltip-surface, popover-border Controls temporary layers and depth

Common dark-mode mistakes

Most dark-mode problems come from treating it as a finish layer instead of a system. A site can look impressive in a static mockup and still fail in forms, data tables, charts, focus states, or long reading contexts.

  • Inverting the light theme and shipping the result without role-level testing.
  • Using absolute black and pure white everywhere, then wondering why the interface feels harsh.
  • Creating only one dark surface and relying on invisible shadows for elevation.
  • Leaving muted text, disabled text, placeholders, and metadata below comfortable readability.
  • Copying light-mode brand and semantic colors without reducing chroma or tuning lightness.
  • Using color alone for errors, warnings, selected states, required fields, or chart meaning.
  • Forgetting focus rings, hover states, active states, form controls, scrollbars, and autofill.
  • Dimming images globally instead of creating asset-specific dark-mode rules.
  • Hard-coding component colors instead of using theme tokens.
  • Ignoring forced-colors, high contrast, and user preference settings.

How Hue Codex supports dark-mode work

Hue Codex can help turn dark-mode decisions into real values. Use the picker and converter to inspect exact colors, the tint and shade tools to explore ramps, the contrast checker to test foreground and background pairs, the color blindness simulator to check distinguishability, and the CSS tools to export ready-to-use values.

The most useful workflow is iterative: choose candidate tokens, test them in a real component, adjust lightness and chroma, retest contrast, then document the values as role-based tokens. Dark mode gets good by testing the actual interface, not by admiring isolated swatches.

Build candidate palettes

Use color conversion, tint and shade, harmonies, and palette generation to create surface, accent, and semantic ramps.

Verify accessibility

Use contrast and accessible pair tools to check text, icons, focus, borders, controls, and state colors.

Export ready-to-use values

Use CSS and token tools to document the final theme values for design and engineering.

Sources and further reading

This guide is written from practical UI design-system work and cross-checked against W3C CSS and WCAG references for color schemes, user preferences, CSS color, contrast, and color-only meaning.

Try it in Hue Codex

Use the free tools to test the idea immediately: pick a color, convert it, generate harmonies, build tints and shades, check contrast, and export practical CSS or palette data.

Quick answers

Dark mode color guide FAQ

What is the best background color for dark mode?

There is no universal best value. Many interfaces work better with near-black or deep charcoal instead of absolute black because it leaves room for surface hierarchy, borders, shadows, and comfortable text.

Should dark mode use pure black?

Sometimes, especially for OLED-focused media experiences, but many apps and websites are more comfortable with near-black surfaces. Test the actual reading and UI density before choosing.

Can I invert my light theme to make dark mode?

Use inversion only as a rough exploration. A production dark theme needs separate surfaces, text, borders, focus, semantic states, images, charts, and tokens.

Does WCAG contrast apply to dark mode?

Yes. Text, icons, controls, focus indicators, and other important visual elements still need to meet the relevant contrast requirements against their actual backgrounds.

Why does white text on black feel uncomfortable?

Very high contrast can feel harsh in dense reading contexts, especially with thin type or bright displays. Near-white text on near-black surfaces often feels more comfortable while still supporting readability.

Why do bright colors look stronger in dark mode?

Dark surrounding surfaces make saturated colors feel more intense. Large bright fills can glow or dominate the interface, so dark themes often use lower chroma for large areas and reserve vivid color for small accents.

Do semantic colors need dark-mode variants?

Yes. Error, warning, success, info, selected, disabled, and focus colors should be tuned separately for dark backgrounds and tested in real components.

How many dark surfaces do I need?

Most interfaces need at least page, base, raised, hover, selected, input, overlay, and border roles. Dense apps may need more specific table, chart, sidebar, and code-editor roles.

What is color-scheme in CSS?

color-scheme tells the browser which color schemes an element supports. It can affect browser-rendered UI such as form controls and scrollbars.

What is prefers-color-scheme?

prefers-color-scheme is a media feature that lets CSS respond to the user preference for light or dark color schemes.

Should a site follow system dark mode automatically?

Often yes, but products with long sessions should also consider a manual setting for system, light, and dark. Users may need different themes in different environments.

Do images need dark-mode versions?

Sometimes. Logos, screenshots, illustrations, charts, and maps may need reversed versions, borders, alternate screenshots, or separate palettes to work on dark backgrounds.

Is OKLCH useful for dark mode?

Yes. OKLCH can help create more perceptually even ramps, especially for surface, accent, and semantic color scales. Final values still need gamut and contrast testing.

How should I name dark-mode tokens?

Name tokens by role, such as surface-page, text-primary, border-subtle, action-primary, and status-danger. Role names are easier to maintain than names tied to one visible color.