How to Enable Dark Mode on Your Website with Pure CSS?
Tags: css, darkmode, materialdesign
Published: 2019-12-29 08:28:21


<blockquote>
Nowadays, more and more devices start to support dark mode. Therefore, we will have to create our website with dark mode support inevitably in the future. In this article, I will show you some tricks to enable dark mode on your website with just pure CSS. And also shows you a few tools and tips you can use when you're designing a website with dark mode support.
</blockquote>


First of all, let introduce some CSS we will use on our examples.

### 1. CSS custom properties (CSS variables)
We can define a custom property and then use it through `var()`

```css
/* define the property */
:root {
  --main-color: black;
}
/* use the property */
p {
  color: var(--main-color);
}
```

`var()` support the second parameter as a fallback.

```css
p {
  color: var(--main-color, darkgray);
}
```

And we can use `var()` inside the `var()`.
```css
p {
  color: var(--main-color, var(--second-color));
}
```


### 2. Prefers-color-scheme
The prefers-color-scheme CSS media feature is used to detect if the user has requested the system to use a light or dark color theme.

```css
@media (prefers-color-scheme: dark) { 
  ... some style for dark mode
}

@media (prefers-color-scheme: light) {
  ... some style for light mode
}
```

Unfortunately, both attributes are not supported by IE. For CSS variables, I personally love [this solution](https://stackoverflow.com/questions/44271920/css-variables-with-fallback-for-older-browsers) by using SASS mixin. And there are some others you can find on GitHub.


## Examples
Now we know how to use those CSS attributes. Let's jump into our examples.

### 1. Load the system setting
The idea is pretty straightforward. Just set all the colors as custom properties. Then do the media query to switch the setting.

```css
/* set light mode color as default value */
:root {
  --bg-color: #ffffff75;
  ...
}
/* switch to dark mode color */
@media (prefers-color-scheme: dark) {
  --bg-color: #121212;
  ...
}
/* apply CSS varaible through var() */
* {
  background: var(--bg-color);
  ...
}
```

[https://codepen.io/oahehc/pen/wvBqjMR](https://codepen.io/oahehc/pen/wvBqjMR)
{% codepen https://codepen.io/oahehc/pen/wvBqjMR %}


### 2. Switch with toggle-button
Because some devices aren't supported dark mode yet. So we still have to provide the toggle button for our users to switch from light and dark mode.
Here we use the checkbox to allow us to access the checked status through CSS.

```css
/* light mode colors */
:root {
  --bg-color: #ffffff75;
  ...
}
/* apply dark mode colors when button is checked */
input:checked, input:checked + * {
  --bg-color: #121212;
  ...
}
/* apply CSS varaible through var() */
* {
  background: var(--bg-color);
  ...
}
```

[https://codepen.io/oahehc/pen/OJPjZXB](https://codepen.io/oahehc/pen/OJPjZXB)
{% codepen https://codepen.io/oahehc/pen/OJPjZXB %}


### 3. Combine both of them
For better user experience, we can combine both examples above. Load the system setting as the default. Then displays the toggle-button for the user to customize.

```html
<!-- we will need two buttons -->
<input class="dark" type="checkbox" />
<input class="light" type="checkbox" />
<article>
  ...
</article>
```

```css
/* deafult light mode color */
:root {
  --bg-color: #ffffff75;
  ...
}
/* hide light button if system setting is light mode */
@media (prefers-color-scheme: light) {
  .light {
    display: none;
  }
}
/* hide dark button if system setting is dark mode and apply dark mode colors */
@media (prefers-color-scheme: dark) {
  .dark {
    display: none;
  }
  --bg-color: #121212;
  ...
}
/* swith to dark mode when dark button checked */
.dark:checked,
.dark:checked + * + * {
  --bg-color: #121212;
  ...
}
/* swith to light mode when light button checked */
.light:checked,
.light:checked + * {
  --bg-color: #ffffff75;
  ...
}
/* apply css variable */
* {
  background: var(--bg-color);
  ...
}
```

[https://codepen.io/oahehc/pen/GRgvdxw](https://codepen.io/oahehc/pen/GRgvdxw)
{% codepen https://codepen.io/oahehc/pen/GRgvdxw %}


## Design Guideline & Tools
There are some properties that come from the [material design](https://material.io/design/color/dark-theme.html) that is worth to take a look.

- <b>Contrast:</b> Dark surfaces and 100% white body text have a contrast level of at least 15.8:1
- <b>CDepth:</b> At higher levels of elevation, components express depth by displaying lighter surface colors
- <b>CDesaturation:</b> Primary colors are desaturated so they pass the Web Content Accessibility Guidelines' (WCAG) AA standard of at least 4.5:1 at all elevation levels
- <b>CLimited color:</b> Large surfaces use a dark surface color, with limited color accents (light, desaturated and bright, saturated colors)


Use Chrome dev-tool can help us check that.
![dev-tool](https://i.imgur.com/H4R9mMx.png)

And here is an online tool can help us generate the color with different tone- [Color Shades Generator](https://javisperez.github.io/tailwindcolorshades/#/).
![color-shade](https://i.imgur.com/cx2TJtb.png)

--

## Conclusion
That's everything I want to share with you. Thanks for the reading and I hope this article can help you to enable the dark mode on your website. Feel free to leave any comments or suggestions.


### Reference
- https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
- https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
- https://stackoverflow.com/questions/44271920/css-variables-with-fallback-for-older-browsers
- https://material.io/design/color/dark-theme.html
- https://javisperez.github.io/tailwindcolorshades/#/