We, as developers who blog, don't need JavaScript to support dark mode!
In fact, if you use JS to make dark mode work, it most likely won't work for users who have it disabled.
I will attempt to convince you that you don't need any JS and minimal CSS to get dark mode to work for your blog site. And I shall show you how to do it.
color-scheme
meta tag or CSS property
Use color-scheme
will get your site to look decent by making use of the browser's defaults for dark mode.
You can use either the meta tag1 or the CSS property2, but prefer the meta tag. Reason stated below.
Meta tag
<!-- add this inside the <head> tag -->
<!-- the order in which you write defines the preferred color scheme if none specified by the OS setting -->
<meta name="color-scheme" content="dark light" />
One would prefer the use of this meta tag instead of CSS to prevent a flash of unstyled content (FOUC):
Honoring the color-scheme CSS property requires the CSS to be first downloaded (if it is referenced via
<link rel="stylesheet">
) and to be parsed. To aid user agents in rendering the page background with the desired color scheme immediately, a color-scheme value can also be provided in a [meta tag.]3
Demo for using the color-scheme
meta tag
CSS property
:root {
color-scheme: dark light;
/* the order in which you write defines the preferred color scheme if none specified by the OS setting */
}
Demo for using the color-scheme
CSS property
- One significant advantage of using
color-scheme
is that you don't have to write any extra styles to make things readable. The user-agent (browser) stylesheet will take care of it. So you can support dark mode with little to no extra CSS.
prefers-color-scheme
media query to override user-agent styles
Use the Now if you don't like the browser's default styles for dark mode, you can override them using the prefers-color-scheme
media query4.
<meta name="color-scheme" content="dark light" />
<style>
@media (prefers-color-scheme: dark) {
body {
background-color: #111; /* Default on Chrome is black (#000) */
color: #eee; /* Default on Chrome is white (#fff) */
}
}
</style>
Having already set the color-scheme
you will only need to worry about those elements whose user-agent stylesheet you don't particularly like.
For example, Chrome sets black as the background and white as the default text color, but designers don't recommend using pure black and white. GitHub's dark mode sets #c9d1d9
as the text color and #0d1117
as the background color in dark mode. These are easier on the eyes than browser defaults.
Demo for using color-scheme
meta tag with prefers-color-scheme
media query
Use some JS if you really want (still an unsatisfactory solution)
Now, some of you might be itching to add some JS.
Well, in my opinion, you don't really need it, but one can argue that the user might find it time-consuming to go into their OS settings to change the appearance setting.
To solve that, you can give them a button to quickly change the dark mode setting directly on your site.
I would do the following.
- Respect the user's OS setting using the
color-scheme
meta tag andprefers-color-scheme
media query as mentioned above. - On top of that, allow them to override the above directly on the page. We can use a button to toggle dark mode using some JS.
<head>
<meta name="color-scheme" content="dark light" />
<style>
html {
color: darkslateblue;
background-color: oldlace;
}
@media (prefers-color-scheme: dark) {
html {
color: ivory;
background-color: darkslategray;
}
}
.dark {
color: ivory;
background-color: darkslategray;
}
.light {
color: darkslateblue;
background-color: oldlace;
}
</style>
</head>
<body>
<button id="toggle-dark">Toggle dark mode</button>
<!-- some content -->
<script>
const toggleDarkModeButton = document.getElementById("toggle-dark");
toggleDarkModeButton.addEventListener("click", () => {
// Check if top level element has a dark class
const manualDarkMode = Array.from(
document.documentElement.classList
).includes("dark");
// Toggle dark mode
if (manualDarkMode) {
document.documentElement.classList.remove("dark");
document.documentElement.classList.add("light");
} else {
document.documentElement.classList.remove("light");
document.documentElement.classList.add("dark");
}
});
</script>
</body>
demo for manually overriding OS appearance setting with JS But using JS still poses problems with elements you haven't explicitly overridden styles for, say, scrollbars on overflowing content. You may not even be able to solve that entirely because of the lack of CSS properties to style several elements (e.g. scrollbars)
Conclusion
In conclusion, it's best to use the color-scheme
meta tag with prefers-color-scheme
media query to support dark mode properly. Using JS is mostly going to worsen the user experience.
Demo for using color-scheme
meta tag with prefers-color-scheme
media query
- TODO: video for the whole article, link video clips to each h2 here.