Dark Mode - Unmistified! 🐱‍👤
Tags: beginners, css, tutorial, webdev
Published: 2020-08-03 15:07:32

**Disclaimer!**
This is going to be a long post. I will try and assimilate all the resources and information I have on a proper dark mode implementation on your website.
<br />
<img src="https://media.giphy.com/media/LTFbyWuELIlqlXGLeZ/giphy.gif">

## CSS Filter Hack!

{% link https://dev.to/akhilarjun/one-line-dark-mode-using-css-24li %}

I have explained this setup in my previous post. And I should repeat, it is only a hack and not a proper flawless dark theme implementation.

## JS Implementation

So now we know, how to make an awesome dark mode using CSS. For the above-mentioned implementation, the javascript idea is very straightforward.

```js
const html = document.getElementsByTagName('html')[0];
const toggleTheme = (theme) => {
    html.dataset.theme = theme;
}
```

And now all you have to do is call the `toggleTheme()` method from UI with `dark` and `light` values respectively.

## Native Dark/ Light mode ?

Am I telling you, that you can detect system preference for light/ dark mode from CSS or js?

Absolutely I am!
<br />
![Heck Yeah](https://media.giphy.com/media/3o6YgraEUsSADbX2Ba/giphy.gif)

### Say hello to the sassy new Media Queries!
<br/>
```html
<script>
  // If `prefers-color-scheme` is not supported, fall back to light mode.
  // In this case, light.css will be downloaded with `highest` priority.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
        'beforeend',
        '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">'
    );
  }
</script>
<!--
  Conditionally either load the light or the dark stylesheet. The matching file
  will be downloaded with `highest`, the non-matching file with `lowest`
  priority. If the browser doesn't support `prefers-color-scheme`, the media
  query is unknown and the files are downloaded with `lowest` priority (but
  above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="/light.css" media="(prefers-color-scheme: light)">
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css">
```

What the above code does is, it checks for any preference set by the user regarding light mode/ dark mode. And according to this preference, the browser downloads appropriate CSS files.

> One thing to note is even though the system preference would be for the dark mode, the browser does download the other CSS as well but with the lowest priority.

Now, what if we want to do all of it in javascript? 
- dynamically check what is the preferred color scheme
- override theme in the application if the user wants to
- remember that decision by the user using `localStorage`

I would say totally doable!
<br />
![No way](https://media.giphy.com/media/3ov9jLsBqPh6rjuHuM/giphy.gif)

## Enter Javascript magic!

**Self-advertisement Warning Rolling In** 😎😁

This is a library I built using vanilla js which does exactly what we have been discussing. And reducing your workload to just two lines

Include the js file
```html
<script src="https://cdn.jsdelivr.net/gh/akhilarjun/tinylibs@latest/themejs/theme.min.js" onload="setupThemeIcon()"></script>
```

And an image with id `theme-selector` and onclick function as `switchTheme(this)`
```html
<img src="./sun.svg" 
    data-light-src="./sun.svg" 
    data-dark-src="./moon.svg"
    alt="light theme" 
    id="theme-selector"
    onclick="switchTheme(this)">
```
<br />
`data-light-src` and `data-dark-src` if provided will be used to swap between icons while changing the theme attribute of `Html` tag.

## Mic Drop Time 🎤
The library will even auto-detect the system preference change and switch themes between dark and light. 

And we will try doing this using chrome dev tools.
<br />
![Result](https://dev-to-uploads.s3.amazonaws.com/i/2819jwmsvatqrvxlsnp6.gif)

That's it for today guys. Cheers! Its Coffee time.
My days are fueled with coffees and only coffees. So I know, you know what we all should do 🤞
<br />
[<img src="https://cdn.buymeacoffee.com/buttons/lato-orange.png" alt="Buy Me A Coffee" height="51px" width="217px">](https://www.buymeacoffee.com/akhilarjun)
<br />
![Well done](https://media1.giphy.com/media/l4pTii07Gypi3GFPy/giphy.gif)

### References
- [web.dev - prefers-color-scheme](https://web.dev/prefers-color-scheme/)
- [Why Browsers download stylesheets with non-matching media queries](https://blog.tomayac.com/2018/11/08/why-browsers-download-stylesheets-with-non-matching-media-queries-180513/)
- [All my gifs](https://giphy.com/)