Skip to main content

Detecting The User's Color Scheme Preference With CSS

Detecting The User's Color Scheme Preference With CSS



If you’re a developer, chances are that you use dark mode on your machine and code editor. If not, what are you waiting for? Join the dark side!

Jokes apart, it is common nowadays to allow users to select a different theme when visiting a website. Now you can do this with CSS only, not the theme selection itself, for that you still need JS but with CSS you can now detect the user’s machine color scheme (light or dark) and display the correct colors on your website immediately.

To do this we need to use the CSS variables. According to the website Can I use, the “CSS variables” feature is available on 95% of the currently used browsers around the world.

We also need to use the prefers-color-scheme media query, which according to Can I use is supported by about 90% of the currently used browsers.

In this article, I will show you how to use the CSS variables and the prefers-color-scheme to setup the default colors of the website depending on the user’s preference, then I will also show you how to toggle the themes using JavaScript.

First, we need to create a basic project, open your terminal and create a new directory somewhere in your machine

mkdir css-theme-detection-example


Navigate inside that directory

cd css-theme-detection-example


Create an HTML file

touch index.html


Add the following content

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- CSS variables (theme) -->
    <link rel="stylesheet" href="variables.css" />
    <!-- The page style -->
    <link rel="stylesheet" href="style.css" />
    <title>CSS theme detection example</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <!-- Button that we will use to toggle the theme -->
    <button id="toggle">Toggle theme</button>
    <!-- JavaScript code -->
    <script src="app.js"></script>
  </body>
</html>

I’ve already added two CSS files and one JS file in the HTML so let’s create them

touch variables.css


touch style.css


touch app.js

Head into the variables.css file, we will now start defining the two colors palettes, add the following content

:root {
  /* Light */
  --light-palette-background: #ffffff;
  --light-palette-text: #000000;

  /* Dark */
  --dark-palette-background: #000000;
  --dark-palette-text: #ffffff;
}

The :root pseudo-class represents the root element of the document, being the <html> tag. It is useful to declare CSS variables globally.

We now have two variables --[theme]-palette-background and --[theme]-palette-text for each theme. The goal is to display a white background with black text when the theme is light and the opposite when the theme is dark.

Let’s add the media queries to define the variables depending on the user OS/browser theme, still in the same file, add the following content

/* If user's system preference is light or unknown */
@media (prefers-color-scheme: light) {
  :root {
    --palette-background: var(--light-palette-background);
    --palette-text: var(--light-palette-text);
  }
}

/* If user's system preference is dark */
@media (prefers-color-scheme: dark) {
  :root {
    --palette-background: var(--dark-palette-background);
    --palette-text: var(--dark-palette-text);
  }
}

We’ve created new variables --palette-background and --palette-text, they will have a different value depending on the media queries.

Let’s update the page style to test it, add the following content in the style.css file

body {
  background-color: var(--palette-background);
  color: var(--palette-text);
}

You can now open the website and you should see the theme matching your OS/browser color scheme.

To serve the website I use the serve Node.js library, which requires you to have Node.js and NPM installed. To use it, simply run

npx serve

and you should be able to view the example at http://localhost:5000

If you change your OS/browser color scheme then refresh the page, it should change accordingly.

What if the user has dark mode enabled on his OS but prefers to view the page in light mode? Well, we can add a toggle button for that and override the default theme.

First, we need to add some extra rules to the CSS, add the following at the end of the variables.css file

/* If user specifically chose light theme */
:root[data-theme="light"] {
  --palette-background: var(--light-palette-background);
  --palette-text: var(--light-palette-text);
}

/* If user specifically chose dark theme */
:root[data-theme="dark"] {
  --palette-background: var(--dark-palette-background);
  --palette-text: var(--dark-palette-text);
}

We just declared two new rules, basically if the <html> tag has a data-theme attribute that is equal to light or dark then we override the media queries, which is why it needs to come after in the CSS file.

Now we need some JavaScript to allow the user to change the theme by clicking on the toggle button, add the following content to the app.js file

/**
 * Get the current theme from the HTML element if it has a "data-theme"
 * attributes, otherwise try to find the theme using the "prefers-color-scheme"
 * media query
 * @returns {"light" | "dark"} "light" or "dark"
 */
function getCurrentTheme() {
  // Find the <html> element
  const root = document.getElementsByTagName("html")[0];

  // Check if the <html> element has a "data-theme" attributes
  if (root.hasAttribute("data-theme")) {
    // Return the value of the "data-theme" attribute
    return root.getAttribute("data-theme");
  }

  // If the <html> element does not have a "data-theme" attribute
  // Use the "matchMedia" function to check if the "prefers-color-scheme"
  // media query matches "dark"
  const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
  // If true, return "dark"
  if (mediaQuery.matches === true) return "dark";
  // Otherwise, return "light"
  return "light";
}

// Self-executing function
(() => {
  // Find the <html> element
  const root = document.getElementsByTagName("html")[0];
  // Retrieve the theme toggle button
  const toggleButton = document.getElementById("toggle");

  // Add an onClick event on the theme toggle button
  toggleButton.addEventListener("click", () => {
    // Use the "getCurrentTheme" function to retrieve the current theme
    const currentTheme = getCurrentTheme();

    // Change the theme to the opposite by adding/changing
    // the "data-theme" attribute on the <html> element
    if (currentTheme === "dark") {
      root.setAttribute("data-theme", "light");
    } else {
      root.setAttribute("data-theme", "dark");
    }
  });
})();

I’ve added comments to the code so that you can understand what is going on. But to summarize, I declared a getCurrentTheme function that will retrieve the current theme either from the data-theme attribute on the <html> element or using the media queries. Then there is a self-executing function that will add the onClick event on the toggle button.

That’s it, we now have a working example! When the page loads it will display the theme matching the user’s OS/browser preference and if the user prefers to change the theme manually, they can use the toggle button.

If you want to continue further, I have two little challenges that you should try to solve to improve the theme experience:

  • Challenge #1: Using the LocalStorage, save the user’s theme preference and change the theme accordingly when refreshing the page.
  • Challenge #2: Using an EventListener, try to automatically change the theme of your website when changing your OS/Browser theme.

That’s where the guide ends, I hope it was helpful.

Comments

Popular posts from this blog

Top 10 Python Frameworks Ranked on Github

  Top 10 Python Frameworks Ranked on Github A framework is a library that makes building web applications easier. Frameworks provide a structure for developers so they can focus more on the business logic of their applications. Python has one of the largest ecosystems with a great number of different libraries, frameworks, and tools for developers. Let's take a look at the best Python  frameworks for web development . Here is a list of the ten highest-ranked Python frameworks  on GitHub. Django    Django is an open-source framework that makes things very fast and scalable. It enables programmers to develop apps and websites of different complexity within a short time. Django's advantages are reusability of components, less code, low coupling, and a principle of not repeating. Moreover, the framework is easy to use. You don't need special tools to develop a Django project. You can write it in a typical text editor, such as notepad. In this way, Django is easy to learn for be

1.Change windows password without knowing the existing password

We all know that to change password in windows we need to enter the existing password and then we can proceed to enter the new password.However there is a trick to change password without knowing the existing password. This trick comes handy when the system is logged in and we have forgotten the password or to pull a prank on your friend(do it at your own risk) Step 1: Right click on computer and select manage Step 2: click on Local users and Groups and click on users. On the right pane you will see list of users. step 3: Right click on any user whose password you want to change and click on set password: step 4: click on proceed(Don’t worry about the message) step 5: Enter the new password step 6: Click on ok and your password will change. You can even use the same method to change HOMEGROUP password. (NOTE: This trick works on WIN 7, 8 , 8.1 ,10)