Create a Super Simple Light/Dark Mode Switch
Tags: webdev, css, javascript
Published: 2021-07-07 07:45:18


It seems like more and more websites are developing dark modes and many people prefer dark modes as it can cause less eye strain, especially in low light. This should be considered when developing any website today. 

Luckily a dark mode switch is very easy to implement with a few lines of JavaScript and some CSS custom properties. 

First of all, we need to think about the technical implementation. It's possible to use the [prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media query in CSS and not use any JavaScript, however I believe that dark mode should always be a choice of the user as many websites implement dark mode horribly. 

## Setting up dark mode

So the first step is to write a JavaScript snippet to place into the top of the `<head></head>` of the document. This should be inlined into the top of the head so that it is executed as early as possible on page load.  

```html
<script type="text/javascript">
  document.documentElement.classList.toggle(
    'dark',
    localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
  );
</script>
```

The above toggle class conditional adds a `dark` class to the HTML tag if `localStorage.theme` is set to dark or `prefers-color-scheme` is dark. 

## Toggling dark mode 

Next, we need to implement the toggle functionality. This needs to do a few things; update the local storage (so that when the user reloads the page the preference is restored) and also toggle the `dark` class on the `<html>` tag. 

The functionality can be implemented in many ways, but here's a simple example. If you are using a JavaScript library then the code will be completely different, this is just a vanilla JavaScript implementation. 

```js
document.addEventListener('DOMContentLoaded', () =>
  document.querySelectorAll('[toggle-dark-mode]').forEach((item) =>
    item.addEventListener('click', () => {
      localStorage.setItem('theme', localStorage.theme == 'dark' ? 'light' : 'dark');
      document.documentElement.classList.toggle('dark');
    })
  )
);
```

The above code simply adds a click event listener to all elements with the `toggle-dark-mode` HTML attribute. Clicking the element should then update local storage and toggle the dark mode class. 

Example button:

```html
<button toggle-dark-mode>Toggle dark mode</button>
```

## Styling for dark mode

If you are using [Tailwind](https://tailwindcss.com/), dark mode should now be functional. You can simply add the `dark:` prefix to any class names for modifications in dark mode. 

CSS custom properties are widely supported cross browser and simplify the effort required for colour mode theming.

Here's some example CSS to get started:

```css
:root {
  --color-bg: #fff;
}

html.dark {
  --color-bg: #000;
}

body {
  background-color: var(--color-bg);
}
``` 

It's assumed that the default colour theme will be light mode, so it's safe to place all default colour properties inside `:root {}`. 

Dark colour theme changes can be placed inside of the `html.dark {}` selector, which will override the root properties. 

Et voila! You now have a basic dark mode implementation. 

## Whats next?

But wait, theres more! 

Many media queries are planned for release with the [Media Queries Level 5](https://drafts.csswg.org/mediaqueries-5/) spec. So keep a watch out for other colour modes, especially [prefers-contrast](https://drafts.csswg.org/mediaqueries-5/#prefers-contrast) which will allow us to easily implement more accessible colour modes.