My Notes for Dark Mode Implementation
September 21, 2021 • ☕️ 4 min read
Around a year ago, I had started implementing dark mode for one of my projects. At that time, I had gone through a lots of reading to get into the nitty gritty details of the implementation. A day before yesterday one of my colleagues ask me to recollect thoughts on the same. Hence, I jotted down the points, ready for your reference and I hope that this make a useful post for you. Don’t forget to share if you find it useful.
-
Themes Toggling :
- Custom class names like
.light .dark - Custom attribute like
dark="true" - Separate stylesheets
- Server side initialization (cookies, database)
- Custom class names like
-
Dark Mode Detection (Set at OS Level) :
-
CSS (
91.96%supported at the time of publishing):@media (prefers-color-scheme: dark) -
JS:
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");⚠️ Issue: “flash of incorrect theme” (
FOIT)
-
-
Storing User Preference :
-
Local Storage:
- Suffers from
FOIT
- Suffers from
-
Cookies:
- Avoids
FOIT
- Avoids
-
Database:
- Avoids
FOIT
- Avoids
Note: I recommend using hybrid approach to avoid any potential FOIT & enhanced UX. The set of methods depends on your scenarios & requirements.
-
-
Inform The Browser About Your Theme Modes (User Agent Styles) :
- Avoids slightest potential FOIT
-
HTML: (recommended)
<meta name="color-scheme" content="dark light"> -
CSS: (
Support: 88.1%, ⚠️ No Firefox support):root { color-scheme: light dark; }
-
Color Palette :
- Lower saturation (
200 tonematerial UI recommends) (50-400range is also ok ) - A dark grey rather then black [ It is easier to see shadows on grey. Hence it leads to expression of wider range of color, elevation, and depth ] (
#121212material UI recommended) - Contrast ratio:
4.5:1 AA rating(text, images, primary color ),3:1 AAA rating(large text) - Contrast ratio:
15.8:1(dark surfaces) - Check accessibility: Web Accessibility Evaluation Tool
- Limited use of brand color
- Colors: Background (0dp elevation surface overlay), Surface (with 1dp elevation surface overlay), Primary, Secondary, On background, On Surface, On Primary, On Secondary
Oncolors are basically font color, border color, etc which are used over background color- You can also have one or more variant of primary & secondary color as well
- Reserve bright colors for smaller surfaces
- Lower saturation (
-
Typography :
- Font Weight should be less then lighter theme (White text look extra bold on black background)
- De-saturated shade of pure white (reduce opacity)
- Material UI Guidelines for text emphasis: 87%, 60%, 38% (opacity value starting from the highest emphasis text)
-
Images :
- Decrease brightness & increase contrast, so that it looks comfortable to eyes against the dark background
-
Typical values:
- Brightness: -20%
- Contrast: +20%
-
Can use different pictures based on OS dark mode setting
<picture> <!-- Use this image if OS setting is light mode or unset --> <source srcset="my-light-photo.jpg" media="(prefers-color-scheme: light) or (prefers-color-scheme: no-preference)"> <!-- Use this image if OS setting is dark mode --> <source srcset="my-light-photo.png" media="(prefers-color-scheme: dark)"> </picture>⚠️ Caution: Two separate files & does not account for toggling
-
Elevation :
- Elevation is inversely proportional to opacity (means lighter the surface color more is the elevation)
- Shadows are replaced by elevation
- However if you want to use shadow then use
dark shadow in dark mode, do not invert the color of shadow used in light theme. - Dark Primary can be used with increased opacity for the nearest background element
- Note the opacity of
5% to 20% for dark primary + 100% dark grey shade backgroundwill create a substantial effect on background color.
-
React Related :
-
Going for styled components?
- Use
ThemeProvidercomponent from styled component library -
Examples:
- Use
-
Want to use CSS stylesheets?
- Go for custom attribute or custom class method
-
🎉 🎉 🎉 Thats all folks! See below for further readings & references 🎉 🎉 🎉