Dark mode: the "best" way (IMO)
Tags: webdev, tutorial, html, beginners
Published: 2020-09-19 10:43:14

## This blog post provides you a quick TL;DR for the ***best*** way to implement dark mode into your website.

Difficulty: ***Beginner***


### So, did I mean by the ***best***?

* Browser support
* Performance
* Simplicity

**In my opinion**; though, there are supporting facts.

### ---- Let's jump right into it: ----

There are many ways to implement dark mode:
* `data-theme="theme"`
* [`@media(prefers-color-scheme)`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) [link](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)
* Seperate CSS files (Don't walk this path please)
* [classList toggle](https://www.w3schools.com/howto/howto_js_toggle_dark_mode.asp)

I'm specifically promoting the `data-theme` method. Click [here](#code) if you can't bother about the others.
###*Why choose `data-theme`?*:
* amazing browser [support.](https://caniuse.com/?search=data-*)
* lightweight.
* clean code.

###For other methods:


{% collapsible @media(prefers-color-scheme) %} 

Use @media(prefers-color-scheme) if you're against legacy browsers. Here's [why.](https://caniuse.com/?search=prefers-color-scheme)

{% endcollapsible %}


{% collapsible Seperate CSS files %} 

Please, for the love of developers - don't use this method. Having seperate CSS files will negatively impact your webpage rendering speed. More CSS files means more `HTTP Requests` are sent to fetch your files, in which will consequently slow down the rendering process.

{% endcollapsible %}

{% collapsible classList toggle %} 

Well... if you're experienced, you probably heard of the `classList.toggle` method. Yeah, it works exactly the same as `data-theme`. Feel free to use it without [guilt](#Seperate CSS files).

{% endcollapsible %}

###Code
Now that the explanation's done, let me show you an example.
####Codepen Example####

{% codepen https://codepen.io/timming-au/pen/VwaGbbW default-tab=none,result %}

###HTML
I used pug for my HTML, but incase you don't know what's going on:
```html
<div id="container">
  <div id="theme-text">Hi, I'm light theme</div>
  <div id="theme-switch">Click me to change theme</div>
</div>
```
###CSS
I used SCSS as my preprocessor; worry not, I didn't put any SCSS stuff in here. To access the attributes associated with the element, use *square brackets*. In this case, `data-theme="dark"` is to be accessed when its value is "dark".
```css
:root{
  --color-bg:#faf7f0;
  --color-font:#363636;
}

body[data-theme="dark"]{
  --color-bg: #282930;
  --color-font: #b1b3bd;
}

body{
  background-color:var(--color-bg);
  color:var(--color-font);
  font-size:1.5rem;
  transition:.2s background-color,.2s color;
}

#container{
  display:flex;
  align-items: center;
  justify-content: center;
  flex-direction:column;
  margin-top:35vh;
}

#theme-switch{
  border:1px var(--color-font) solid;
  margin-top:1rem;
  padding:1rem;
  border-radius:1rem;
  user-select:none;
  cursor:pointer;
}
```
You **will need** to use *variables* if you want it clean. You can create variables to store any value, with the syntax:
`--+name:value` 
Make sure you create them in `:root` to prevent scope problems.

###JS
This is vanilla javascript. :) Noticed how I used the `localStorage.setItem` method. This works ***only*** for the client browser. If you want it to work for the *same user* on *any* client, check out [SSP.](https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Introduction)
```javascript
const themeText = document.getElementById("theme-text")
const themeSwitch = document.getElementById("theme-switch")
if (window.localStorage.getItem("theme") === "dark"){
  document.body.dataset.theme = "dark";
  themeText.innerHTML = "Hi, I'm dark theme";
}
themeSwitch.addEventListener("click",function(){
  if(document.body.dataset.theme !== "dark"){
    document.body.dataset.theme = "dark"
    themeText.innerHTML = "Hi, I'm dark theme"
    window.localStorage.setItem("theme","dark")
  }else{
    document.body.dataset.theme = "light"
    themeText.innerHTML = "Hi, I'm light theme"
    window.localStorage.setItem("theme","light")
  }
})
```
The `data-theme` attribute in `body` is accessed with `dataset.theme` in JS.

###---------End---------

There you go! This is how you can easily add dark mode without any *regrets*. Though, remember that this is only a small part of the module - at least let me guide you for the design.

[My design]
(https://codepen.io/timming-au/pen/mdPzYPO)

[Dark mode design examples](http://letmegooglethat.com/?q=codepen+dark+mode+toggle)


<3