I'm trying to make a dark/light theme toggle on my website. The SVG file switches back and forth on every click, but there's an issue with the theme not switching every click.
First two clicks - theme changes as expected.
Third and fourth clicks - SVG image still changes each click, but theme doesn't change
Fifth and sixth clicks onward - theme changes as expected, cycle repeats
HTML:
<div id="themes">
<img id="current-theme">
</div>
CSS:
body{
background-color: #ccc;
}
#themes {
text-align: right;
margin-right: 10em;
margin-top: 2em;
transform: scale(1.5);
cursor: pointer;
}
.dark-mode {
background-color: rgb(65, 65, 65);
transition: background-color 0.5s ease;
h1 {
color: white;
}
h3 {
color: white;
}
button {
background-color: white;
color: black;
}
}
.light-mode {
background-color: #ccc;
transition: background-color 0.5s ease;
h1 {
color: var(--primary-color);
}
h3 {
color: black;
}
button {
background-color: black;
color: white;
}
}
Javascript:
//default theme is light
document.getElementById("current-theme").src = "images/moon.svg"
var currentTheme = document.getElementById("current-theme");
currentTheme.setAttribute("onClick", "toDarkTheme()");
var theme = document.body;
function toDarkTheme() {
document.getElementById("current-theme").src = "images/sun.svg";
theme.classList.toggle("dark-mode");
//currentTheme.removeAttribute("onClick");
currentTheme.setAttribute("onClick", "toLightTheme()");
}
function toLightTheme() {
document.getElementById("current-theme").src = "images/moon.svg";
theme.classList.toggle("light-mode");
//currentTheme.removeAttribute("onClick");
currentTheme.setAttribute("onClick", "toDarkTheme()");
}
I've included a link to the code in jsfiddle so you can see exactly what's happening. Thank you for any help/advice you can give!
This kind of error is typical when you have too much JavaScript. In this example I just control the theme with the classname of the body element. All elements in the page are children of the body element and therefore it is easy to style them accordingly.
I inserted both images, so I don't need to manipulate the DOM further and then show/hide them based on the body classname as well.
//default theme is light
document.body.classList.add("light-mode");
document.getElementById("themes").addEventListener('click', e => {
if(document.body.classList.contains("light-mode")){
document.body.classList.replace("light-mode", "dark-mode");
}else{
document.body.classList.replace("dark-mode", "light-mode");
}
});
#themes {
float: right;
margin-right: 10em;
margin-top: 1em;
transform: scale(1.5);
cursor: pointer;
}
.dark-mode #themes img, .light-mode #themes img {
position: absolute;
display: none;
}
.dark-mode #themes img.sun {
display: block;
}
.light-mode #themes img.moon {
display: block;
}
.dark-mode {
background-color: rgb(65, 65, 65);
transition: background-color 0.5s ease;
}
.dark-mode h1 {
color: white;
}
.light-mode {
background-color: #ccc;
transition: background-color 0.5s ease;
}
.light-mode h1 {
color: black;
}
<div id="themes">
<!--The icon and theme will change on click-->
<img class="sun" src="images/sun.svg" alt="sun"/>
<img class="moon" src="images/moon.svg" alt="moon"/>
</div>
<h1>Mode</h1>
At the beginning theme.classList is empty
Then with each subsequent click, you get the following state changes...
I.e. dark-mode adds or cancels dark-mode, it doesn't do anything to light-mode and vice-versa.
You could give both functions both toggles provided you toggle light-mode explicitly at the beginning. Like this...
//default theme is light
document.getElementById("current-theme").src = "images/moon.svg"
var currentTheme = document.getElementById("current-theme");
currentTheme.setAttribute("onClick", "toDarkTheme()");
var theme = document.body;
theme.classList.toggle("light-mode");
function toDarkTheme() {
document.getElementById("current-theme").src = "images/sun.svg";
theme.classList.toggle("dark-mode");
theme.classList.toggle("light-mode");
//currentTheme.removeAttribute("onClick");
currentTheme.setAttribute("onClick", "toLightTheme()");
}
function toLightTheme() {
document.getElementById("current-theme").src = "images/moon.svg";
theme.classList.toggle("light-mode");
theme.classList.toggle("dark-mode");
//currentTheme.removeAttribute("onClick");
currentTheme.setAttribute("onClick", "toDarkTheme()");
}
body{
background-color: #ccc;
}
#themes {
text-align: right;
margin-right: 10em;
margin-top: 2em;
transform: scale(1.5);
cursor: pointer;
}
.dark-mode {
background-color: rgb(65, 65, 65);
transition: background-color 0.5s ease;
h1 {
color: white;
}
h3 {
color: white;
}
button {
background-color: white;
color: black;
}
}
.light-mode {
background-color: #ccc;
transition: background-color 0.5s ease;
h1 {
color: var(--primary-color);
}
h3 {
color: black;
}
button {
background-color: black;
color: white;
}
}
<div id="themes">
<!--The icon and theme will change on click-->
<img id="current-theme">
</div>