Search code examples
javascripthtmlcsstoggledarkmode

Body CSS not updating with .setProperty()


I am trying to enable a dark mode/light mode feature on a website, in which I am using the .setProperty function to change the HEX value of a variable. However, whenever I toggle a switch, the site does not update. Why is this? Here is all the code pertaining to the issue:

let color = "#141414";

function changeMode() {
  
  console.log("Switch was toggled. Switching site color scheme...")
  
  let bg = document.querySelector(':root');
  
  // Should switch the value of 'color' from grey to white, and vice versa
  if (color === "#141414") { color = "#ffffff"; } else if (color === "#ffffff") {  color = "#141414"; }
  
  bg.style.setProperty("--main2", color);

}
:root {

  --main1: #ffdb15;
  --main2: #141414;

}

html, body {

  background-color: var(--main2);
  
}

.switch {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 34px;
  left: 20px;
  top: 20px;

}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ccc;
  -webkit-transition: .4s;
  transition: .4s;
}

.slider:before {
  position: absolute;
  content: "";
  height: 26px;
  width: 26px;
  left: 4px;
  bottom: 4px;
  background-color: white;
  -webkit-transition: .4s;
  transition: .4s;
}

input:checked + .slider {
  background-color: #5d00e2;
}

input:focus + .slider {
  box-shadow: 0 0 1px #5d00e2;
}

input:checked + .slider:before {
  -webkit-transform: translateX(26px);
  -ms-transform: translateX(26px);
  transform: translateX(26px);
}

.slider.round {
  border-radius: 34px;
}

.slider.round:before {
  border-radius: 50%;
}
<label class = "switch" onclick = "changeMode()">
  <input type = "checkbox" checked>
  <span class = "slider round"> </span>
</label>

Is the problem in the color variable, or in the program not updating the page's body itself when the value is switched?

Edit: Also, if you know of any way to improve my code, please let me know how. Specifically, is there any way to improve the method that switches the value of the color variable?


Solution

  • If you look at the console while clicking the input you can see it's triggering two click events, effectively toggling it twice at once. You can add console.log(event) in changeMode() to see exactly what events are triggering (label click and the input click). The quick fix is to change it to trigger on the input change, rather than parent label click:

    <label class = "switch">
       <input onchange="changeMode()" type = "checkbox" checked>
       <span class = "slider round"> </span>
    </label>