Dark/Light mode - HTML and CSS, JavaScript if you'd like
In this tutorial, I’ll show you a few different methods of enabling a light/dark mode toggle switch, and the pros and cons to each. The examples will include support for the new prefers-color-scheme
media query.
Here’s an example of what a pure CSS dark mode toggle switch will end up looking like: Pure CSS dark/light toggle
So, let’s dive right in:
Method 1: Pure CSS mode toggle button
The first method I’ll cover is making a pure CSS toggle button. This is just a basic example, make sure you customize this to fit the style of your site.
We’ll start by creating a basic HTML page. We’ll include a checkbox and label that we’ll end up turning into the toggle button, and a <main>
section to hold all of the page’s content.
<!doctype html>
<html>
<head>
<title>Darkmode Example</title>
<!-- css will go here -->
</head>
<body>
<input type="checkbox" name="toggleMode" id="toggleMode"><label for="toggleMode"></label>
<main>
<!-- put your main content here -->
</main>
</body>
</html>
Next, let’s start adding some CSS. Personally, I prefer to use CSS Variables do we don’t have to update every element with two styling rules.
In this example, we’ll have two variables: --background
for the background of the page, and --color
for the color of the content. These variables will be declared for the <main>
element so we can change them based on the checkbox’s state.
main{
--color:black;
--background:white;
}
The next step is to change these variables when the checkbox is checked. Will do this by using the Genral Sibling Combiner (~
) and the :checked
selector.
#toggleMode:checked ~ main{
--color:white;
--background:black;
}
We now have a basic toggle switch created. Let’s update the label based on the current mode, do people know what will happen when they click on it. We can also hide the checkbox since clicking on the label will toggle it. We’ll use the :before
pseudo-element to update the label’s text.
#toggleMode{
display:none;
}
#toggleMode + label:before{
content:'enable dark mode';
}
#toggleMode:ckecked + label:before{
content:'enable light mode';
}
Here’s all the CSS we have so far:
main{
--color:black;
--background:white;
}
#toggleMode:checked ~ main{
--color:white;
--bakcground:black;
}
#toggleMode{
display:none;
}
#toggleMode + label:before{
content:'enable dark mode';
}
#toggleMode:ckecked + label:before{
content:'enable light mode';
}
So far, we’ve created a basic functioning mode toggle switch. In the next part, let’s explore adding support for the prefers-color-scheme
media query.
Adding support for prefers-color-scheme
If you haven’t heard about it yet, the prefers-color-scheme
media query lets you check what color scheme is selected on an OS level - here’s more information on that.
To implement prefers-color-scheme
, we’ll basically make a media query with the opposite CSS as we had before.
Let’s start by creating a media query for prefers-color-scheme
:
@media (prefers-color-scheme:dark){
/** default to dark mode here **/
}
Next, we’ll add CSS that works the opposite way as the previous code - default to dark mode and let users toggle to light mode.
The code below should be placed inside the previous media query.
/** default to dark mode **/
main{
--color:white;
--background:black;
}
#toggleMode:checked ~ main{
--color:black;
--background:white;
}
We’ll also need to update the label to reflect the default dark mode (again, this should be placed inside the media query):
#toggleMode + label:before{
content:'enable light mode';
}
#toggleMode:ckecked + label:before{
content:'enable dark mode';
}
There you go - the mode will automatically default to dark mode when prefers-color-scheme
is set to dark
.
Lastly, let’s explore another method of using JavaScript to create a dark mode.
JavaScript dark mode
In this method, we’ll use JavaScript to change the mode of the page. The advantage of using JavaScript is the ability to save the user’s preference, and next time they load the page you can load it with their preference still selected.
In this example, we’ll use a button to update the color mode.
<!doctype html>
<html>
<head>
<title>JavaScript dark mode</title>
<!-- css will go here -->
</head>
<body>
<button id="toggleMode">toggle dark mode</button>
<script>
//javascript goes here
</script>
<!-- main content goes here -->
</body>
</html>
In this example, we’ll be adding the dark mode via a class we add to the <html>
element. Then we can create a separate CSS selector for dark mode by using .dark
. I won’t include the dark mode CSS here because it should be pretty easy to figure out.
Here’s how we’ll update the class using javascript:
//default to light mode
var mode = 'light';
if (localStorage.getItem("mode")){
//check if there's a saved state already
mode = localStorage.getItem("mode");
} else if (window.matchMedia('(preferes-color-scheme:dark)')){
//check if dark mode is preferred
mode = "dark";
}
//update the class based on the mode
document.documentElement.className = mode;
//when the button is clicked, toggle the mode and save the change in local storage
document.getElementById('toggleMode').onclick = function(){
mode = (mode === 'dark') ? 'light' : 'dark';
document.documentElement.className = mode;
localStorage.setItem("mode", mode);
}
That’s the basics of implementing a dark mode. Try it out and see what you think, you can email any questions or thoughts to [email protected].