Creating a css theme toggle
web-dev ~ 2019-04-24I 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.
- Ideally, define your variables only in the theme toggle
- 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
- When the checkbox is selected, the selectors change the values of the variables
- The selectors for the theme are applied to all the siblings of the checkbox
- Every element beside the checkbox has access to the variables
- Use a more specific selector to change the value of a variable already defined
- This allows for the difference of theme-defined variables and default variables for a given component