Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

140
Views
Changing between themes with Javascript

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!

https://jsfiddle.net/6op0fx7L/2/#&togetherjs=zTrev7ILNd

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

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>

about 4 years ago · Juan Pablo Isaza Report

0

At the beginning theme.classList is empty

Then with each subsequent click, you get the following state changes...

  1. theme.classList becomes dark-mode
  2. theme.classList becomes dark-mode, light-mode
  3. theme.classList becomes light-mode
  4. theme.classList becomes empty

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>

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!