Dark Mode Contrast
title: "Dark Mode Contrast" weight: 22 description: "Learn how to ensure sufficient color contrast in dark mode: lighter text on dark backgrounds, avoiding pure white text on pure black, maintaining contrast for interactive states, and using semantic color tokens." date: 2026-06-28 lastmod: 2026-06-28 tags: [accessibility, color-contrast]
Dark mode requires careful contrast management because the same contrast ratios behave differently on dark backgrounds -- pure white text (#fff) on pure black (#000) has a ratio over 21:1, which can cause eye strain, while mid-gray text may become illegible.
## What You'll Learn
You will design accessible dark mode color palettes, test contrast on dark backgrounds, avoid common dark mode pitfalls, and implement dark mode with CSS custom properties.
## Why It Matters
Dark mode is requested by many users, but poorly implemented dark mode can be harder to read than light mode. Text needs sufficient brightness to be legible, and interactive elements need adequate contrast against dark surfaces.
## Real-World Use
A site implements dark mode by inverting colors. White text on dark gray works well, but links change from blue to light blue that has only 2.5:1 contrast against the dark background. Users cannot read the links. The fix uses a lighter blue (#66B3FF) for links in dark mode.
## Dark Mode Contrast Flow
```mermaid
flowchart TD
A[Dark Mode Design] --> B[Set Background]
A --> C[Set Text Colors]
A --> D[Set Interactive Colors]
B --> E[Dark #1a1a1a to #2d2d2d]
C --> F[Text: #e0e0e0 minimum]
D --> G[Links: 3:1 against bg]
E --> H[Verify text contrast]
F --> H
G --> H
Designing Dark Mode Colors
Use semantic color tokens that adapt between modes rather than hard-coding dark colors.
<!-- Dark mode toggle -->
<button id="theme-toggle" aria-label="Toggle dark mode">
<span class="icon-light">Light</span>
<span class="icon-dark">Dark</span>
</button>
/* Semantic color system with dark mode */
:root {
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--text-primary: #1a1a1a;
--text-secondary: #555555;
--link-color: #0056b3;
--link-hover: #003d80;
--border-color: #cccccc;
}
[data-theme="dark"] {
--bg-primary: #1a1a1a;
--bg-secondary: #2d2d2d;
--text-primary: #e0e0e0;
--text-secondary: #a0a0a0;
--link-color: #66b3ff;
--link-hover: #99ccff;
--border-color: #444444;
}
/* Verify dark mode contrast */
/* --text-primary #e0e0e0 on --bg-primary #1a1a1a: ~12:1 -- passes */
/* --text-secondary #a0a0a0 on --bg-primary #1a1a1a: ~5.5:1 -- passes AA */
/* --link-color #66b3ff on --bg-primary #1a1a1a: ~4.8:1 -- passes AA */
// Dark mode contrast validator
function validateDarkModeColors() {
const darkBg = getComputedStyle(document.documentElement)
.getPropertyValue('--bg-primary').trim();
const pairs = [
{ name: 'Primary text', fg: '--text-primary' },
{ name: 'Secondary text', fg: '--text-secondary' },
{ name: 'Link text', fg: '--link-color' },
{ name: 'Border', fg: '--border-color' }
];
pairs.forEach(pair => {
const fg = getComputedStyle(document.documentElement)
.getPropertyValue(pair.fg).trim();
const ratio = getContrastRatio(fg, darkBg);
const passes = ratio >= 4.5;
console.log(`${pair.name}: ${ratio.toFixed(1)}:1 - ${passes ? 'PASS' : 'FAIL'}`);
});
}
Common Mistakes
- Using pure black (#000) as dark mode background
- Using pure white (#fff) for text on dark backgrounds
- Simply inverting light mode colors
- Not testing interactive states (hover, focus) in dark mode
- Using the same accent colors that work in light mode
- Not adjusting image and icon brightness for dark mode
- Forgetting about shadows and elevation in dark mode
Practice and Challenge
Practice 1: Check contrast of all text colors in dark mode on your site. Practice 2: Verify link color in dark mode passes AA. Practice 3: Test focus indicator visibility in dark mode. Practice 4: Check button contrast in both default and hover states. Practice 5: Verify border and divider contrast in dark mode.
Challenge: Create a complete dark mode color system that passes WCAG AA for all text and UI components. Include at least 15 semantic tokens: text (3 levels), background (3 levels), interactive (primary, secondary, danger), link, border, focus, and surface (3 levels). Document the contrast ratio for each foreground-background pair in dark mode.
FAQ
Mini Project
Create a dark mode contrast testing tool. Load a page in dark mode, extract all CSS custom properties, and validate contrast for every semantic color pair. Generate a report showing which pairs pass and fail, with suggested alternative colors for failures.
What's Next
Gradient and Background Contrast covers contrast testing for gradients and complex backgrounds.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro