Creating a css theme toggle



I finally did it! As you should see in the sidebar/header there is now a toggle which allows you to display a dark theme. If you have javascript enabled the site will remember your choice using a cookie. If you do not have javascript enabled the site will warn you that the choice cannot be saved.

Let me show you how I did it.

A brief overview of the concepts

  • Utilize the no-js checkbox trick for changing css
  • Convert nearly all color values into css variables
  • set css variables using the state of the checkbox

There are two major concerns with ensuring the variables stick.

  1. Ideally, define your variables only in the theme toggle
  2. Otherwise you must use more specific selectors to override variables for specific components

I have an example of both in my css which I will explain.

No-JS Toggle

My toggle is directly based off this how to at W3

Essentially, you place a <input type="checkbox" id="chk"> in your code. You create a <label for="chk"> which acts as your button. Then using some fancy css selector trickery, you can change values based of the :checked status of the checkbox.

The difference between the W3 exmaple and mine will be clear. In their example they places the checkbox inside the label. I place mine in the root and the label lives wherever I want.

Code

View on Codepen.io (it has some extras to make it actually look good)

<body>
    <input type="checkbox" id="theme">
    <div class="sidebar"></div>
    <div class="content"></div>
</body>
#theme         ~ * { --theme-bg-color: white; }
#theme:checked ~ * { --theme-bg-color: black; }
.content {  background-color: var(--theme-bg-color);  }


#theme:checked ~ * .sidebar { --bg-color: var(--theme-bg-color); }
.sidebar {
    --bg-color: brown;
    background-color: var(--bg-color);
}

Explanation

  1. When the checkbox is selected, the selectors change the values of the variables
  2. The selectors for the theme are applied to all the siblings of the checkbox
  3. Every element beside the checkbox has access to the variables
  4. Use a more specific selector to change the value of a variable already defined
  5. This allows for the difference of theme-defined variables and default variables for a given component
Comments are loading... I hope ;)