Dark Mode Implementation Guide: CSS, JavaScript and System Preference
Dark mode reduces eye strain and extends battery life. This guide covers CSS variables, JavaScript theme switching, and system preference detection.
Last updated:What is Dark Mode and Why Does It Matter?
Dark mode (dark theme) is an interface mode that displays dark backgrounds with light text. It reduces eye strain in low-light environments.
On OLED screens, dark mode can extend battery life by 30-60% because dark pixels are turned off. This is a significant advantage for mobile devices.
User preference: With system-level dark mode support (macOS, Windows, iOS, Android), users expect a consistent experience across all applications.
Accessibility: Some users (photophobia, migraine) prefer dark themes. Dark mode provides accessibility benefits for these users.
Theme Management with CSS Variables
CSS custom properties (variables) let you manage theme colors centrally. Define the default (light) theme in :root selector, dark theme in [data-theme="dark"] selector.
Example: :root { --bg: #ffffff; --text: #1a1a1a; } [data-theme="dark"] { --bg: #1a1a1a; --text: #e0e0e0; }. All styles use these variables.
Color transitions: body { background: var(--bg); color: var(--text); transition: background 0.3s, color 0.3s; } provides smooth theme transition.
Contrast control: Follow WCAG contrast ratios in dark mode too. Light text on dark background requires 4.5:1 contrast ratio.
Shadows and borders: Shadows (box-shadow) are less visible in dark mode. Use borders to make element boundaries more distinct.
Theme Switching with JavaScript
Theme toggle button: When user clicks the button, change theme with document.documentElement.setAttribute('data-theme', 'dark').
Saving preference: Save user's choice with localStorage.setItem('theme', 'dark'). Read with localStorage.getItem('theme') when page loads.
FOUC prevention: To prevent Flash of Unstyled Content (FOUC), apply theme setting with inline script in <head>. This determines theme before page renders.
Toggle function: function toggleTheme() { const current = document.documentElement.getAttribute('data-theme'); const next = current === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', next); localStorage.setItem('theme', next); }
Detecting System Preference
prefers-color-scheme media query: Apply styles based on system preference in CSS with @media (prefers-color-scheme: dark) { :root { --bg: #1a1a1a; } }.
Detection with JavaScript: Check system dark mode preference with window.matchMedia('(prefers-color-scheme: dark)').matches.
Listening for changes: Track system theme changes with matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { if (e.matches) setDark(); else setLight(); }).
Priority order: 1. User manual selection (localStorage), 2. System preference (prefers-color-scheme), 3. Default theme (light). Check in this order.
Dark Mode Best Practices
Don't use pure black (#000000). Very dark gray (#121212 or #1a1a1a) looks better and reduces eye strain.
Reduce color saturation. Bright colors (red, green, blue) in dark mode cause eye strain. Use desaturated colors.
Adjust images. Bright images can be jarring in dark mode. Slightly darken images with filter: brightness(0.8).
Test all components. Forms, tables, code blocks, charts should look correct in dark mode. Check every component in dark mode.
Meta theme-color: Set browser UI (address bar) color to match dark mode with <meta name="theme-color" content="#1a1a1a" media="(prefers-color-scheme: dark)">.
Dark Mode in Frameworks
Tailwind CSS: Define dark mode styles with dark: prefix. Like dark:bg-gray-900 dark:text-white. Provides manual control with class strategy.
React: Easy dark mode implementation with useDarkMode hook or next-themes library. SSR-compatible theme management.
Vue: Reactive dark mode with useDark composable from @vueuse/core library. Automatic system preference detection.
Bootstrap: Bootstrap 5.3+ dark mode support with data-bs-theme="dark" attribute. Theme management with CSS variables.
Related tools
Practical articles on this topic
White Text on a Green Button: Measure Before Choosing
A bright green sign-up button may attract attention while its white label remains uncomfortable to read.
Web Accessibility: WCAG, ARIA and Inclusive Design
Web accessibility ensures that people with disabilities can use websites.
Web Accessibility Audit: WCAG Compliance and Audit Process
Web accessibility audit is a systematic process that evaluates your site's compliance with WCAG standards.