60 lines
1.9 KiB
Markdown
60 lines
1.9 KiB
Markdown
|
# Dark Mode
|
||
|
|
||
|
## 1. Saving/Loading state
|
||
|
|
||
|
**LocalStorage**
|
||
|
Saving/Loading the current theme in LocalStorage is quite easy on the frontend it works for static apps that do not have a server. But it only works when Javascript is enabled and it can take a second to load the current theme which may cause some flickering.
|
||
|
|
||
|
**Cookie Session**
|
||
|
If you have a server rendering the webpage this is the better approach imho, because we can inject a ```<body class=”theme-dark/>``` into the html and this causes the current theme to be immediately available on the client.
|
||
|
|
||
|
## 2. Applying the Theme
|
||
|
|
||
|
From mind there are two methods of changing the colors.
|
||
|
|
||
|
**File based**
|
||
|
We can create two files ```theme-light.css``` and ```theme-dark.css``` and decide which one to load based on the current theme.
|
||
|
|
||
|
The advantage of this is that we can put anything we want into these files and even change layout based on the theme. This is also a disadvantage as we need to always keep two css files in sync with our html markup.
|
||
|
|
||
|
**Variable based**
|
||
|
CSS Variables are now widely [available in all browser](https://caniuse.com/css-variables). We can use this to our advantage because we can avoid duplicating our css styles by injecting the theme variables into the markup.
|
||
|
|
||
|
```css
|
||
|
:root {
|
||
|
/* primary */
|
||
|
--primary-source: rgb(255, 142, 60);
|
||
|
}
|
||
|
|
||
|
body {
|
||
|
|
||
|
}
|
||
|
|
||
|
body.theme-dark {
|
||
|
--text-color: var(--)
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## 3. Detecting user preferences
|
||
|
We can also detect if the user prefers a light or dark theme using ```prefers-color-scheme```. This API is available in css:
|
||
|
|
||
|
```css
|
||
|
.theme-a {
|
||
|
background: #dca;
|
||
|
color: #731;
|
||
|
}
|
||
|
@media (prefers-color-scheme: dark) {
|
||
|
.theme-a.adaptive {
|
||
|
background: #753;
|
||
|
color: #dcb;
|
||
|
outline: 5px dashed #000;
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
|
||
|
```javascript
|
||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
|
||
|
const newColorScheme = event.matches ? "dark" : "light";
|
||
|
});
|
||
|
```
|