I try to help

Dark Mode using only CSS

CSS

Approximate reading time: 1 minute(s)

While doing some research for another article I decided to add a dark mode toggle to my website, but I don't want to add Javascript to my site at all. The question is, how do you add a dark mode toggle without using Javascript?

The Javascript way

Let's first explore the Javascript version to see how it might work.

This is our simple example HTML, nothing fancy here.

<div class="content">
  Some content
</div>
<label for="dark-mode">Toggle Dark Mode
<input type="checkbox" id="dark-mode" /></label>
:root {
  --lightBackground: white;
  --lightColor: black;
  
  --darkBackground: black;
  --darkColor: white;
  
  --background: var(--lightBackground);
  --color: var(--lightColor);
}
.content {
  background: var(--background);
  color: var(--color);

  height: 3rem;
}

We define our colors and we assign them to our container - which can be body if you so desire.

const checkbox = document.querySelector('#dark-mode');
const content = document.querySelector('.content');

checkbox.addEventListener('change', (e) => {
  const isDark = e.target.checked;
  
  if (isDark) {
    content.style.setProperty("--background", "var(--darkBackground)");
    content.style.setProperty("--color", "var(--darkColor)");
  } else {
    content.style.setProperty("--background", "var(--lightBackground)");
    content.style.setProperty("--color", "var(--lightColor)"); 
  }
})

When the status of the checkbox changes, we change the CSS custom property value in kind. Simple, right? This comes with the added benefit that if we reference --background or --color anywhere else inside our element it will inherit these values!

The CSS Way

We can achieve the toggle part using the :checked pseudo-class selector and by positioning the toggle before the content, we can then style our content using the general sibling combinator(~) combinator. This is the reason why I haven't placed the input tag inside the label like in the first example.

<input type="checkbox" id="dark-mode" />
<label for="dark-mode">Toggle Dark Mode</label>
<div class="content">
  Some content
</div>
:root {
  --lightBackground: white;
  --lightColor: black;
  
  --darkBackground: black;
  --darkColor: white;
  
  --background: var(--lightBackground);
  --color: var(--lightColor);
}
.content {
  background: var(--background);
  color: var(--color);

  height: 3rem;
}
#dark-mode ~ .content {
  --background: var(--lightBackground);
  --color: var(--lightColor);
}
#dark-mode:checked ~ .content {
  --background: var(--darkBackground);
  --color: var(--darkColor);
}

We can also create a fancier version using CSS custom property fallback as a hacky if statement.