Colorise ProOKLCH Engine
ExploreStudioNamesPickerPairs
ExploreStudioNamesPickerPairsContrastExtract
Menu

Product

  • Home
  • Explore
  • Studio
  • Color Names

Tools

  • Picker
  • Color Pairs
  • Contrast
  • Image Extract
  • Gradient Lab
  • Palette Diff
  • Brand from URL

Guides

  • All guides
  • OKLCH vs HSL
  • WCAG vs APCA
  • OKLCH color scales
  • Gamut & sRGB
  • Extract from images
  • HEX to OKLCH
  • Dark mode colors
  • Color meanings

Guides/Dark mode

Dark mode color palettes

如何构建兼顾对比度与品牌色相的深色模式调色板:在 OKLCH 中反转明度、补偿彩度,并用 WCAG 和 APCA 检查颜色对。

Why naive inversion fails

The tempting shortcut — invert the light theme, or mirror every color's lightness — produces dark UIs that feel wrong in three predictable ways: brand blues turn electric, greys go muddy, and text either glares or sinks. The reason is that perceived lightness, chroma and contrast do not mirror symmetrically. OKLCH gives you independent control of exactly those three things, which is why a deliberate mapping beats an inversion.

The OKLCH method

  1. Move surfaces down, not to black. Large backgrounds live around L 0.15–0.25 (a slate like #0f172a sits at L 0.208). Pure black removes your ability to layer cards and borders above the background.
  2. Bring text up, not to white. Body text around L 0.88–0.95 keeps contrast enormous without the halation of pure white on near-black. A light surface like #f8fafc (L 0.984) becomes your text color's neighbourhood, slightly dimmed.
  3. Keep hue, trim chroma. Your brand hue stays the same number — that is what makes the theme recognisably yours. Reduce chroma about 10–25% and lift lightness a little for accents, because saturated colors gain intensity against dark backgrounds.
  4. Rebuild elevation with lightness steps. In dark mode, “higher” surfaces are lighter (the opposite of shadows). Even L steps — 0.18, 0.22, 0.26 — give a calm elevation ladder because OKLCH steps are perceptually even.

Check the pairs, both metrics

Dark pairs are where WCAG ratios and APCA disagree most: WCAG treats white-on-black and black-on-white as the same ratio, while APCA (designed with polarity in mind) rates light text on dark backgrounds differently from the reverse. Use WCAG 2.2 for compliance and APCA as the readability sanity check — the WCAG vs APCA guide covers the details, and every pair can be tested in the contrast checker before it ships.

Why not pure black?

A #000000 page with #ffffff text is the maximum possible WCAG ratio (21:1), so it always passes, and on OLED panels true black can save power. The drawbacks are practical. Some readers, notably many people with astigmatism, report that bright text on a pure black field glows or smears (often called halation); the effect varies between people and displays, so treat it as a comfort risk rather than a rule. And with nothing darker than the page, borders and cards have nowhere to go. A dark slate such as #111827 with off-white text such as #e5e7eb keeps contrast very high without the glare.

Elevation without shadows

Drop shadows nearly vanish on dark backgrounds, so layered interfaces usually express height with lightness instead: page at the bottom, cards one step lighter, menus and dialogs lighter again. Keep the hue constant and move only L, with a slight chroma tint if your neutrals are tinted toward the brand. Two cautions: re-check text contrast on the lightest surface in the stack, not just the page, and add a faint border where two adjacent surfaces would otherwise merge. The scales guide shows how to generate evenly spaced neutral steps for this.

Contrast targets for dark themes

WCAG 2.2 applies unchanged: at least 4.5:1 for body text, 3:1 for large text, and 3:1 for meaningful non-text elements such as input borders, icons and focus rings (success criterion 1.4.11). APCA, a candidate method for the still-draft WCAG 3, is useful as an extra sanity check but is not a compliance requirement. Its sign encodes polarity: dark text on a light background gives a positive Lc, and light text on a dark background gives a negative one (read the magnitude). The table is calculated on this page, text color first, background second.

Dark-mode text on background: WCAG 2.x ratio and APCA Lc
PairTextBackgroundWCAG ratioAA bodyAPCA Lc
Off-white on dark slate#e5e7eb#11182714.33:1Pass-91.0
White on pure black#ffffff#00000021.00:1Pass-107.9
Muted grey on a raised surface#9ca3af#1f29375.78:1Pass-48.6
Dimmer grey on the same surface#6b7280#1f29373.04:1Fail-24.6
Light-theme brand blue, unchanged#2563eb#0f172a3.45:1Fail-25.7
Same blue at L 0.72, chroma trimmed#71a2ff#0f172a7.07:1Pass-51.5
  • White on black reaches 21:1, yet the off-white slate pair is already above 14:1: there is no readability reason to go to the extreme.
  • The dimmer grey on the raised surface is fine as a 3:1 UI color (placeholder borders, icons) but fails as body text, so keep secondary text one step brighter.
  • The light-theme brand blue #2563eb on dark slate falls short of 4.5:1. Lifting its OKLCH lightness to 0.72 and capping chroma (last row) clears it comfortably. The same check works for any pair in the contrast checker, and the contrast hub lists precomputed combinations.

Adapting brand colors

The usual fix for an accent that is too dark or too loud is to keep its hue, raise L, and trim C rather than just lightening in HSL. In the table above, only lightness and chroma changed between the last two rows. Check the result visually: a lifted blue should still read as the same brand, not a pastel. For a hue-specific starting point, browse a family such as blue, then use the brand tool or the OKLCH picker to adjust. Marketing pages follow the same logic; see the SaaS landing page palettes for pairs that survive both themes.

Implementing the switch

Define colors as CSS custom properties, override them for dark, and let the user choose. A common pattern follows the system setting by default and lets an explicit data-theme attribute win:

:root { color-scheme: light dark; --bg: oklch(0.99 0.005 250); --fg: oklch(0.2 0.02 250); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --bg: oklch(0.2 0.02 250); --fg: oklch(0.92 0.01 250); }
}
:root[data-theme="dark"] { color-scheme: dark; --bg: oklch(0.2 0.02 250); --fg: oklch(0.92 0.01 250); }
:root[data-theme="light"] { color-scheme: light; }

The color-scheme property tells the browser which built-in UI (scrollbars, form controls, default canvas) to render, so set it alongside your own colors. The newer CSS light-dark(lightValue, darkValue) function can collapse the two blocks into one declaration per property, but it depends on color-scheme and on browser support, so check your audience's browsers before relying on it and keep the custom property approach as a fallback. In Tailwind v4 the dark: variant follows prefers-color-scheme by default; to drive it from a toggle, redefine it with @custom-variant dark pointed at your data-theme selector. Persist the choice and set the attribute before first paint to avoid a flash of the wrong theme.

From guide to tokens

Once the mapping feels right for a few seed colors, let Studio generate the full dark ramp set — surfaces, text, borders, accents — from the same OKLCH values and export light and dark themes as matching CSS variables or Tailwind tokens. The scales guide explains how the underlying 50–950 ramps are built, so both themes share one system instead of drifting apart.

FAQ

Should dark mode just invert the light palette?
No. Inverting RGB or flipping HSL lightness breaks hue relationships and contrast. In OKLCH you invert perceived lightness deliberately (surfaces go to L 0.15–0.30, text to L 0.85–0.97), keep the hue, and reduce chroma slightly because saturated colors vibrate against dark backgrounds.
What contrast does dark mode text need?
The same WCAG targets: 4.5:1 for body text at AA. Pure white on pure black (21:1) passes easily but can feel harsh and halate for readers with astigmatism; an off-white around L 0.90–0.95 on a surface around L 0.18–0.25 is usually more comfortable while staying well above the threshold. APCA models this polarity difference explicitly.
Why do brand colors look neon in dark mode?
Saturated colors appear more intense against dark surroundings at the same chroma. Lower chroma by roughly 10–25% for dark surfaces and accents, and raise lightness a little, until the dark variant carries the same visual weight as the light one.
Is pure black a bad dark mode background?
Not wrong, but rarely the best default. Pure black leaves no room to show elevation with lighter surfaces, and some readers find bright white text on pure black harder to read because of glare or halation. A very dark grey or slate gives layered surfaces and softer contrast while still passing WCAG easily. On OLED screens, black can be a deliberate choice.
How do I show elevation in dark mode without shadows?
Make higher surfaces slightly lighter than lower ones. Shadows are hard to see on dark backgrounds, so a ladder of surface lightness (for example OKLCH L 0.18, 0.22, 0.26 with the same hue) separates page, card and popover. Add a subtle border where two surfaces would otherwise blend, and keep text contrast checked on the lightest surface.
Can I use the CSS light-dark() function for theming?
It is a newer CSS feature that picks one of two colors based on the used color scheme, so it can replace duplicated media queries. Check current browser support for your audience before relying on it, and keep a fallback such as custom properties switched by prefers-color-scheme or a data-theme attribute for older clients.

Related

  • Studio
  • Contrast checker
  • WCAG vs APCA
  • Building OKLCH scales
  • Brand palette tool
  • Contrast hub
  • SaaS landing palettes

Ready to try it? Open the OKLCH picker or jump into Studio.

Colorise Pro

Free OKLCH color workspace: precision color picker, color pairs, WCAG & APCA contrast checker, palette from image, Studio systems, names, gradients, and brand tools. Export HEX, CSS, Tailwind & DTCG.

OKLCH Engine

Product

  • Home
  • Explore
  • Studio
  • Color Names
  • Color Codes

Tools

  • Color Picker
  • Color Pairs
  • Contrast Checker
  • Image Extract
  • Gradient Lab
  • Palette Diff
  • Brand from URL
  • For presentations
  • For business cards
  • For SaaS landings
  • Duo pairs
  • Trio systems

Guides

  • All guides
  • OKLCH vs HSL
  • WCAG vs APCA
  • OKLCH color scales
  • Gamut & sRGB
  • Extract from images
  • HEX to OKLCH
  • Dark mode colors
  • Color meanings

Legal

  • Privacy
  • Terms

© 2026 Colorise Pro. All rights reserved.

© 2026 Colorise Pro. Built for precision color work.

Report infringement: [email protected] (Colorise Pro)

PrivacyTermsOKLCH · WCAG · APCA