How to Dark Mode
• ☕️ 12 min readApplying dark mode to an application’s UI has many benefits for the user including a new look & feel and health reasons such as reducing eye strain. While not required for ADA compliance, dark mode can help users with visual disabilities by changing the contrast of text.
For relatively new applications, there is always a feature request for toggling between dark and light mode. Even “older” applications with millions of users put that request in the backlog and some have recently implemented site-wide dark mode for users to toggle.
Implementing light/dark mode on the front-end can be a relatively simple process because of the features offered by the browser such as the media query (prefers-color-scheme: dark)
and matchMedia()
query.
In this article I want to write about how I implemented a light/dark toggle on this portfolio site, what I came across and some of my thoughts on implementing dark mode on the UI.
How Dark Mode Should Be Implemented
Toggling light/dark mode on an application should have three choices:
- Light
- Dark
- System/Automatic
The simplest implementation of light/dark mode is the one that you shouldn’t even have to think about. It starts before you enter the web address in the URL bar in the browser and that’s when you first set up your machine with the appearance that you want.
When you go to a website, the theme of your OS should be shown on the website without you having to explicitly toggle it.
If you’ve set your OS to dark mode, the websites that you go onto should automatically detect the system setting and display in dark mode and vice versa.
If you’ve set your system appearance setting to “automatic” then during the day it’s light mode and at nighttime it’s dark mode.
Now there are instances when a user will prefer the opposite light/dark theme to what their system is set to. The reason can be as simple as, “I like this website better in light mode” or the color scheme is easier to read in a certain mode.
One feature of implementing dark mode that I think should be a requirement is saving the light/dark mode preference to localStorage
so that the set appearance will show on subsequent visits to the user without having to set it again.
Setting values in localStorage
has been made very simple using the API provided by the browser and it can be used to store the preferred light/dark mode that the user set for the website.
Requirements
- As a User, I want the page to load with the preferred color scheme that is set on my OS.
- As a User, I want to be able to set light/dark/automatic theme to the website
- As a User, I want my preferred light/dark mode to be remembered and set on subsequent visits to the website.
Implementation
Light/dark mode is a problem for the UI so client-side JavaScript and HTML/CSS will be the main forefront to tackle this feature.
Starting with the markup, usually a .dark
class or data-attribute set on the <html>
element can be used as a selector for CSS rules to set the write color for each mode. Starting with light mode, by default, is easiest and then writing your dark mode CSS rules for the properties will allow you to write minimal CSS.
/* CSS written above will be the default light */
.dark {}
[data-theme="dark"] {}
JavaScript
Being the lazy programmer that I am and dark mode being a common feature, there are solutions provided by people who have implemented this before and also frameworks provide solutions of themes as well. This JavaScript snippet is from Tailwind’s documentation and provides a simple and clear way to handling setting light/dark mode including the use of setting the theme value in localStorage
.
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
Issues
One issue that I came across while implementing dark mode is my website would have a flash of light mode (FOLM) before the dark mode CSS was set.
This issue comes from the critical rendering path and how the browser paints the page to the screen.
References
https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme