CSS Web Development

CSS Tips – Correct Way to Toggle Dark Mode

In the past, most web developers handled dark mode in CSS by manually adding a specific class (like .dark-mode) to the <body> tag. We would declare our default variables, and then duplicate them within that dark mode class to override the colors.

It was an easy-to-understand method, and it worked. However, it came with a catch: you had to declare variables twice. If you had a large design system, this significantly increased the size of your CSS file and forced you to scroll up and down to manage color pairs.

With recent browser support updates, there is now a cleaner, one-line solution that is easier to maintain and automatically respects user system settings: the light-dark() function.

Here is how to upgrade your dark mode logic.

The Old Way vs. The New Way

The Old Method

Previously, your CSS likely looked something like this. You defined root variables, then overrode them when a specific class was present

:root {
  --bg-color: #ffffff;
  --text-color: #000000;
}

body.dark {
  --bg-color: #000000;
  --text-color: #ffffff;
}

The New Method: light-dark()

With the new function, we can consolidate this logic.

Step 1: Enable the Color Scheme First, you must tell the browser that your page supports both light and dark schemes. This is crucial for the function to work.

:root {
  color-scheme: light dark;
}

Step 2: Use the Function Now, instead of separating the colors, you declare them together. The syntax is light-dark(light_value, dark_value).

:root {
  --bg-color: light-dark(#ffffff, #000000);
  --text-color: light-dark(#000000, #ffffff);
}

This keeps the color logic for a single element in one place. No more scrolling up and down to find the matching pair.

Automatic System Matching

One of the best features of light-dark() is that it works without JavaScript.

If a user changes their operating system (Windows/macOS) to Dark Mode, the CSS will automatically pick the second value in the light-dark() function. You no longer need to write complex @media (prefers-color-scheme) queries just to get the basics working.

Handling the Toggle Switch (JavaScript)

If you want to offer a manual toggle button for your users, the JavaScript logic changes slightly. Instead of toggling a CSS class, you modify the color-scheme property of the root element.

However, there is a potential issue when combining manual toggles with automatic system detection. If a user’s system is Dark, but they manually toggle your site to Light, you want your site to stay Light.

To prevent state mismatches, it is best to initialize the color-scheme in your CSS to a single starting value (e.g., light) if you plan on allowing manual overrides. This ensures the toggle button state matches the visual theme.

const toggle = document.getElementById('darkModeToggle');

document.documentElement.style.colorScheme = 'light';

toggle.addEventListener('change', function() {
    if (this.checked) {
        document.documentElement.style.colorScheme = 'dark';
    } else {
        document.documentElement.style.colorScheme = 'light';
    }
});

Enhancing UX: Persisting Preferences

To make the experience seamless, you should save the user’s preference to Local Storage so they don’t have to toggle the theme every time they revisit your site.

const toggle = document.getElementById('darkModeToggle');
const savedColorScheme = localStorage.getItem('color-scheme');

if(savedColorScheme === 'dark') {
    toggle.checked = true;
    document.documentElement.style.colorScheme = 'dark';
}
else 
    document.documentElement.style.colorScheme = 'light';

toggle.addEventListener('change', function() {
    if (this.checked) {
        document.documentElement.style.colorScheme = 'dark';
        localStorage.setItem('color-scheme','dark');
    } else {
        document.documentElement.style.colorScheme = 'light';
        localStorage.setItem('color-scheme','light');
    }
});

Summary

Here is the source code of this tutorial.

The light-dark() function is a massive quality-of-life improvement for CSS. It reduces code duplication, simplifies maintenance, and integrates natively with browser color schemes.

By combining this with a few lines of JavaScript for Local Storage, you can create a robust, modern dark mode experience with significantly less effort than the old class-based method.

That\'s all for this tutorial. If you like it, check out our YouTube channel and our Twitter to stay tune for more dev tips and tutorials

Written By

Leave a Reply

Your email address will not be published. Required fields are marked *