Reputation: 200
I've been trying to implement persistent dark mode on web pages, as when a user navigates through pages, their choice will be remembered. Also, I added a toggle dark/light mode button, for better user experience. Thus I came up with this code:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#002f30">
<style>
body {
padding: 25px;
color: black;
font-size: 25px;
}
.btn {
background: white;
border: 1px solid #10101c;
color: #10101c;
border-radius:0.5rem;
}
a {
text-decoration: none;
color: #006262;
border-bottom: 1px dotted #192841;
font-style: italic;
}
body.dark {
background-color: #10101c;
color: #778899;
}
body.dark .btn {
background: #10101c;
color: #708090;
border: 1px solid #002e43;
border-radius:0.5rem;
}
body.dark a {
text-decoration: none;
color: #778899;
border-bottom: 1px dotted #d5c4a1;
font-style: italic;
}
</style>
</head>
<body>
<h1 style="margin-top: 0">page 1</h1>
<h2 style="margin-top: 0">Toggle Dark/Light Mode</h2>
<p>Click the button to toggle between dark and light mode for this page.</p>
<p>This is a link to a second page <a href="test2.html">click</a></p>
<button id="mode" class="btn" onclick="toggle()">Toggle dark mode</button>
<script>
function toggle() {
// This bit is for the toggling between dark and light mode
let element = document.body;
element.classList.toggle("dark");
// This part is for toggling the text inside the button
var toggle = document.getElementById("mode");
if (toggle.innerHTML === "Toggle dark mode") {
toggle.innerHTML = "Dark mode it is";
}
else {
toggle.innerHTML = "Toggle dark mode"; }
// This part I copy pasted from one of Kevin Powell's videos on darkmode switch, and maintaining persistence but still couldn't figure out howbit works...
// check for saved 'darkMode' in localStorage
let darkMode = localStorage.getItem('darkMode');
const darkModeToggle = document.querySelector('#mode');
const enableDarkMode = () => {
// 1. Add the class to the body
document.body.classList.add('dark');
// 2. Update darkMode in localStorage
localStorage.setItem('darkMode', 'enabled');
}
const disableDarkMode = () => {
// 1. Remove the class from the body
document.body.classList.remove('dark');
// 2. Update darkMode in localStorage
localStorage.setItem('darkMode', null);
}
// If the user already visited and enabled darkMode
// start things off with it on
if (darkMode === 'enabled') {
enableDarkMode();
}
// When someone clicks the button
darkModeToggle.addEventListener('click', () => {
// get their darkMode setting
darkMode = localStorage.getItem('darkMode');
// if it not current enabled, enable it
if (darkMode !== 'enabled') {
enableDarkMode();
// if it has been enabled, turn it off
} else {
disableDarkMode();
}
});
// This is the solved part I asked earlier, it chages the meta theme color with the dark or light mode change
var meta = document.querySelector("meta[name=theme-color]");
if (meta.getAttribute("content") === "#002f30") {
console.log(meta.getAttribute("content"));
meta.setAttribute("content", "#10101c");
} else {
console.log(meta.getAttribute("content"));
meta.setAttribute("content", "#002f30");
}
}
</script>
</body>
</html>
While running the code, everything works fine except for the persistence part. If dark mode is enabled, and I navigate to a second page of the same html code, it turns back to default light mode. Am I doing the code right?
P.S. I'm a novice/beginner in Javascript
Upvotes: 2
Views: 2177
Reputation: 3526
// Using a local variable since stack overflow doesn't allow localstorage operations for security purposes.
let storage = {darkMode: "disabled"}
function userPreferesDarkMode() {
//return localStorage.getItem("darkMode") === "enabled";
return storage.darkMode === "enabled";
}
function setThemePreference(value) {
// localStorage.setItem("darkMode", value || "disabled");
storage.darkMode = value || "disabled";
}
const enableDarkMode = () => {
// 1. Add the class to the body
document.body.classList.add("dark");
};
const disableDarkMode = () => {
// 1. Remove the class from the body
document.body.classList.remove("dark");
};
function setTheme() {
// If the user already visited and enabled darkMode
// start things off with it on
if (userPreferesDarkMode()) {
enableDarkMode();
} else {
disableDarkMode();
}
const appDiv = document.getElementById("app");
appDiv.innerHTML = `<h1>Dark mode: ${userPreferesDarkMode()}</h1>`;
}
function bootstrap() {
const darkModeToggleButton = document.querySelector("#mode");
darkModeToggleButton.addEventListener("click", () => {
if (userPreferesDarkMode()) {
setThemePreference("disabled");
disableDarkMode();
} else {
setThemePreference("enabled");
enableDarkMode();
}
const appDiv = document.getElementById("app");
appDiv.innerHTML = `<h1>Dark mode: ${userPreferesDarkMode()}</h1>`;
});
setTheme();
}
document.addEventListener("DOMContentLoaded", function(event) {
// Your code to run since DOM is loaded and ready
bootstrap()
});
Live Demo
<!DOCTYPE html>
<html>
<head>
<title>This is document title</title>
<style>
body {
padding: 25px;
color: black;
font-size: 25px;
}
.btn {
background: white;
border: 1px solid #10101c;
color: #10101c;
border-radius:0.5rem;
}
a {
text-decoration: none;
color: #006262;
border-bottom: 1px dotted #192841;
font-style: italic;
}
body.dark {
background-color: #10101c;
color: #778899;
}
body.dark .btn {
background: #10101c;
color: #708090;
border: 1px solid #002e43;
border-radius:0.5rem;
}
body.dark a {
text-decoration: none;
color: #778899;
border-bottom: 1px dotted #d5c4a1;
font-style: italic;
}
</style>
</head>
<body>
<div id="app">hello</div>
<button id="mode" class="btn">Toggle dark mode</button>
</body>
</html>
You have wrapped the checking of stored preference in the toggle
method. So when you navigate to the second page, it doesn't read the value from localstorage
until toggle
method is invoked.
Adding a StackBlitz demo
Upvotes: 2