Pure CSS dark mode support
It is easy to support dark mode with pure CSS. No JavaScript required.
Just define your light and dark theme colours using CSS variables near the top of your stylesheet:
This ties dark mode into the browser and/or OS settings. The light theme variables are not wrapped within a @media
block, and so will be used by default. The dark theme variables are wrapped within @media (prefers-color-scheme: dark) { ... }
, and so will be used only if the user has dark mode enabled in the browser/OS.
If you want a button on the web page for toggling light/dark mode, then you will need to use JavaScript. Personally I’m happy to just rely upon browser/OS settings.
Use of the color-scheme
property is not strictly necessary, but is intended to inform the browser that the element can be “comfortably”1 be rendered in the given colour schemes.
Update the rest of your stylesheet to use these variables for all colours:2
Then in your HTML header, include this line3:
That’s it!
Switching between light and dark mode §
To switch between light and dark mode, use your browser and/or OS settings, e.g.:
- In Windows 10, go to Windows Settings → Personalisation → Colours → Choose your colour, and switch between Light and Dark.
- In Firefox, go to Menu → Settings (or
about:preferences
), then under General scroll down to Language and Appearance. By default, Automatic is selected, which will use the OS setting. To override this, select Light or Dark.
Code highlighting support §
Adding dark mode support for code highlighting using pure CSS is a little more involved.
I’ve written this note purely for that purpose.
The word “comfortably” is used both by MDN and web.dev. That’s putting a lot of trust in the website developers to provide “comfortable” themes! ↩︎
The MDN example shows defining each element twice, one wrapped in
@media (prefers-color-scheme: light) { ... }
and another in@media (prefers-color-scheme: dark) { ... }
. I find it simpler to just have one@media
query for the two sets of variables, and then define each element just once using the variables. Though interestingly, it does note there is an experimentallight-dark()
function, which might offer a simpler alternative in future. ↩︎Again, the
color-scheme
meta tag is not strictly necessary, but helps “user agents in rendering the page background with the desired color scheme immediately”. ↩︎