I'm building an app with a dark mode switch. It works on the first click, but after that, it works on every second click.
(this snippet shows a checkbox. In the project, it looks like a real switch)
Any idea how I can get it to work on a single click?
const body = document.getElementById('body');
let currentBodyClass = body.className;
const darkModeSwitch = document.getElementById('darkModeSwitch');
//Dark Mode
function darkMode() {
darkModeSwitch.addEventListener('click', () => {
if (currentBodyClass === "lightMode") {
body.className = currentBodyClass = "darkMode";
} else if (currentBodyClass === "darkMode") {
body.className = currentBodyClass = "lightMode";
}
});
}
#darkModeSwitch {
position: absolute;
left: 15px;
top: 15px;
}
.darkMode { background-color: black; transition: ease .3s; }
.lightMode { background-color: #FFF; transition: ease .3s; }
#darkModeSwitch input[type="checkbox"] {
width: 40px;
height: 20px;
background: #fff89d;
}
#darkModeSwitch input:checked[type="checkbox"] {
background: #757575;
}
#darkModeSwitch input[type="checkbox"]:before {
width: 20px;
height: 20px;
background: #fff;
}
#darkModeSwitch input:checked[type="checkbox"]:before {
background: #000;
}
<body id="body" class="lightMode">
<div id="darkModeSwitch">
<input type="checkbox" onclick="darkMode()" title="Toggle Light/Dark Mode" />
</div>
</body>
Every time you click on your checkbox, you're adding another eventListener to darkModeSwitch
- Take your addEventListener
out of the function and remove the onclick
Then, you need to move let currentBodyClass = body.className;
inside the darkModeSwitch
function, so that the value is updated each time. Having it outside the function, you're assigning it a value once at run time, and then never updating it
Finally, this makes limited sense
body.className = currentBodyClass = "darkMode";
Instead, just do
body.className = "darkMode";
const darkModeSwitch = document.getElementById('darkModeSwitch');
const body = document.getElementById('body');
//Dark Mode
darkModeSwitch.addEventListener('click', () => {
let currentBodyClass = body.className;
if (body.className === "lightMode") {
body.className = "darkMode";
} else if (currentBodyClass === "darkMode") {
body.className = "lightMode";
}
});
#darkModeSwitch {
position: absolute;
left: 15px;
top: 15px;
}
.darkMode {
background-color: black;
transition: ease .3s;
}
.lightMode {
background-color: #FFF;
transition: ease .3s;
}
#darkModeSwitch input[type="checkbox"] {
width: 40px;
height: 20px;
background: #fff89d;
}
#darkModeSwitch input:checked[type="checkbox"] {
background: #757575;
}
#darkModeSwitch input[type="checkbox"]:before {
width: 20px;
height: 20px;
background: #fff;
}
#darkModeSwitch input:checked[type="checkbox"]:before {
background: #000;
}
<body id="body" class="lightMode">
<div id="darkModeSwitch">
<input type="checkbox" title="Toggle Light/Dark Mode" />
</div>
</body>
Finally, you might want to consider using .classList
when working with an Element's classes, as it will allow you to make use of methods such as .add()
/ .remove()
/ .contains()
- Your current method will fail if the Element has more than one class set at a time, while these methods avoid this
let currentBodyClass = body.classList;
if (currentBodyClass.contains("lightMode")) {
currentBodyClass.add('darkMode');
currentBodyClass.remove('lightMode');
} else if (currentBodyClass.contains("darkMode")) {
currentBodyClass.add('lightMode');
currentBodyClass.remove('darkMode');
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With