Dark theme only CSS, Media Query and also with Javascript
Tags: javascript, css, darkmode, tutorial
Published: 2022-06-28 00:29:39

Code:[Github repo](https://github.com/205mdp/html-css-js-dark-light-theme)
codepen: [Con js y css](https://codepen.io/205mdp/pen/RwQXXwZ)
codepen: [solo css](https://codepen.io/205mdp/pen/oNEKKXB)

## Installation 
### It can be run from any virtual server you have, this point is not 100% necessary.


> First clone the repository and install.

```js
git clone https://github.com/205mdp/html-css-js-dark-light-theme.git

yarn add 
```
## Run 

```js
yarn dev
```

## Option 1 - only css 

- Generate variables that are assigned to the background and colors.

[Documentation CSS Variables](https://developer.mozilla.org/es/docs/Web/CSS/Using_CSS_custom_properties)
```css
/* just variable example */
body {
  /* create variable  */
  --main-back-color: red;
  /* assign variable  */
  background-color: var(--main-back-color); 
}
```
- Generate media query.

```css
:root {
  --background: white;
  --color: black;
}

/* media query dark  */
@media (prefers-color-scheme: dark) {
  :root {
    --background: black;
    --color: white;
  }
}
```

- Conclusion: This simple step takes the browser theme and applies it to the page.

## Option 2 With Javascript and media query

### We detect what configuration the system has.
```js
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    // dark mode
    localStorage.setItem('theme', 'dark');
} else {
    localStorage.setItem('theme', 'light');
}
```
### Schema color change event
```js
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
  event.matches ? enableDarkMode() : disableDarkMode();
});
```

## Option 3 With Javascript manually by button.

It can be done by adding a class to the body .dark , .light we save it in the localStorage too.

```js
// Change from dark mode to light mode. 
const enableDarkMode = () => {
  document.body.classList.add('darkmode');
  // 2. Update darkMode in localStorage
  localStorage.setItem('theme', 'dark');
}
// change from light mode to dark mode.
const disableDarkMode = () => {
  // 1. Remove the class from the body
  document.body.classList.remove('darkmode');
  // 2. Update darkMode in localStorage 
  localStorage.setItem('theme', 'light');
}

```
### Button event
```js
// btn btn-theme
const btnTheme = document.querySelector('#btn-theme');

btnTheme.addEventListener('click', () => {
  // 1. Check if dark mode is enabled
  localStorage.getItem('theme') === 'dark' ? disableDarkMode() : enableDarkMode();

})
```

> Note: There is a better solution to not duplicate both css variables and classes. Which is controlling from JS. We see it in the next branch.

## With Javascript but without media query

- The .lightmode class is removed and the @media (prefers-color-scheme: dark) is removed, everything is done with Javascript and stored in the LocalStorage.

- From css we only have the variables in the root and in the .darkmode class, the .darkmode class is assigned to the body and is removed when it is in light mode, the base root variables being applied.

```css
/* global variables */
:root {
  --header-color: #f5f5f5;
  --header-back-color: rgb(84, 121, 241);
  --main-back-color: #f5f5f5;
  --main-color: #333;
  --header-container-max-width: 70rem;
}

.darkmode {
  --header-color: #b2b2b2;
  --header-back-color: rgb(31, 31, 31);
  --main-back-color: #595959;
  --main-color: rgb(235, 235, 235);
  --header-container-max-width: 70rem;
}
```

- When the page loads we check which theme is on the system and which theme is on the local host. Leave the one found on Localhost.

```js
// Detect system color
const detectColorScheme = () => {
  const localTheme = localStorage.getItem('theme');
  // Check which theme the system/browser has 
  if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    // dark mode
    (localTheme === 'dark' || localTheme === null) ? enableDarkMode() : disableDarkMode();
  } else {
    (localTheme === 'dark') ? enableDarkMode() : disableDarkMode();
  }
}

// Check for changes to the theme and change it
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
  event.matches ? enableDarkMode() : disableDarkMode();
});

// Detect system color
detectColorScheme();

```

- Here, finally, the auxiliary functions and the control of the button to change the theme, between dark and light.

```js
// btn btn-theme
const btnTheme = document.querySelector('#btn-theme');

btnTheme.addEventListener('click', () => {
  // 1. Check if dark mode is enabled
  localStorage.getItem('theme') === 'dark' ? disableDarkMode() : enableDarkMode();

})

// Change from dark mode to light mode. 
const enableDarkMode = () => {
  document.body.classList.add('darkmode');
  // 2. Update darkMode in localStorage
  localStorage.setItem('theme', 'dark');
}
// cambio de light mode a dark mode.
const disableDarkMode = () => {
  // 1. Remove the class from the body
  document.body.classList.remove('darkmode');
  // 2. Update darkMode in localStorage 
  localStorage.setItem('theme', 'light');
}

```

> Final note: you could add more color themes or let the client select the colors and save them to localstorage or the database.

<hr>

> Each point is a different branch on github