About the author
Telmo Goncalves is a software engineer with over 13 years of software development experience and an expert in React. He’s currently Engineering Team Lead at Marley Spoon.
Check out more of his work on telmo.is
I’ve implemented dark/light mode before using styled-components
as well as SCSS
, but much of the same
functionality can be accomplished just using CSS
and a bit of JavaScript.
In this article, I’ll provide a step-by-step guide on how to accomplish this for your own application.
This article assumes the reader has minimal knowledge of HTML, CSS, and working with the command line. For more experienced developers, feel free to skip through to select information as needed.
The CSS
First, create a project with a style.css
file at the root.
This can be done by running the following in the command line:
mkdir light-dark-mode && touch light-dark-mode/style.css
This creates a new directory, called light-dark-mode
, for the project and adds a style.css
file to it.
Navigate to the directory by running:
cd light-dark-mode
In the style.css
file, add the following code for a default, (light) theme:
:root {
--background-color: #fff;
--text-color: #000;
}
To see it working, create an HTML
file by running:
touch index.html
And adding the following HTML
. Notice the style.css
file is imported:
<!DOCTYPE html>
<html>
<head>
<title>Light and Dark Mode</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>Adding light / dark themes</h1>
</body>
</html>
Opening the index.html
file in a browser should display the header text: Adding light / dark themes"
Now we can add some styling. It’s best practice to use variables, denoted as var(--variable-name)
, wherever
possible. This allows for easy re-use and more descriptive code.
In the style.css
file, add:
body {
background-color: var(--background-color);
color: var(--text-color);
}
The page should look exactly the same. That’s because we’re using the style declarations in the :root
pseudo-class.
Now that the scaffolding for the default (light) theme is set up, variables for the dark mode theme can be added.
Add the following to style.css
above the body
declaration:
[data-theme="dark"] {
--background-color: #3F3F3F;
--text-color: #fff;
}
Notice that it’s similiar to the :root
declaration, except the text color is white and the background color is a
dark gray.
So far we’ve set up the project so that:
- The
[data-theme="dark"]
theme can be toggled on/off (we’ll cover how to do this in the section below). - The default appearance will be the light theme. This is why the theme is configured to the
:root
class and not a separate[data-theme="light"]
class.
The JavaScript
Now we can verify the page can adopt the dark mode theme. In the index.html
file, add the following JavaScript
snippet inside the <head>
section:
<script type="text/javascript">
// Wait for document to load
document.addEventListener("DOMContentLoaded", function(event) {
document.documentElement.setAttribute("data-theme", "dark");
});
</script>
Opening the index.html
page in the browser should now reveal a #3F3F3F
(dark) background and #fff
(white) text.
What does this do?
document.documentElement
returns the root Element
of the document. So, even without the JavaScript snippet, the
dark mode could always be applied if the following were applied:
<!DOCTYPE html>
<html data-theme="dark">
<!-- The rest of the code -->
But because the goal is to allow the user to toggle between the light and dark mode themes, JavaScript is required to handle the changing of state.
The Switch
Next, add a button to index.html
that will trigger the theme change.
Inside the <head>
section, modify the JavaScript snippet to the following:
<script type="text/javascript">
// Wait for document to load
document.addEventListener("DOMContentLoaded", function(event) {
document.documentElement.setAttribute("data-theme", "light");
// Get our button switcher
var themeSwitcher = document.getElementById("theme-switcher");
// When our button gets clicked
themeSwitcher.onclick = function() {
// Get the current selected theme, on the first run
// it should be `light`
var currentTheme = document.documentElement.getAttribute("data-theme");
// Switch between `dark` and `light`
var switchToTheme = currentTheme === "dark" ? "light" : "dark"
// Set our currenet theme to the new one
document.documentElement.setAttribute("data-theme", switchToTheme);
}
});
</script>
And add a <button>
to the <body>
section:
<button id="theme-switcher">Switch themes!</button>
What this does is:
- Creates a
button
element that’s visible on the page. - Creates a function so that the theme is changed to dark mode when it’s clicked,
- And back to light if it’s clicked again.
That’s it! Reload index.html
in the browser and try it out.
Telmo regularly posts helpful React development tips and guides on Twitter. Be sure to follow him at @telmo