Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Use Javascript document.body.className to add a body class rather than document.body.setAttribute

Ask Question

I'm using the function below to toggle dark mode in CSS. It uses document.body.setAttribute to add the attribute data-theme="dark" to the document body tag, and removes it when toggled again; and the function reads and/or sets localStorage darkSwitch to hold the dark mode state between page loads. The CSS is i.e. [data-theme="dark"] .myselector {background-color: #000;} .

Function:

<input type="checkbox" class="custom-control-input" id="darkSwitch" />  // Simply the button to toggle
(function() {
  var darkSwitch = document.getElementById("darkSwitch");
  if (darkSwitch) {
    initTheme();
    darkSwitch.addEventListener("change", function(event) {
      resetTheme();
    function initTheme() {
      var darkThemeSelected =
        localStorage.getItem("darkSwitch") !== null &&
        localStorage.getItem("darkSwitch") === "dark";
      darkSwitch.checked = darkThemeSelected;
      darkThemeSelected
        ? document.body.setAttribute("data-theme", "dark")
        : document.body.removeAttribute("data-theme");
    function resetTheme() {
      if (darkSwitch.checked) {
        document.body.setAttribute("data-theme", "dark");
        localStorage.setItem("darkSwitch", "dark"); 
} else {
        document.body.removeAttribute("data-theme");
        localStorage.removeItem("darkSwitch");  
})();

What I want to do is modify the function to not add the data attribute data-theme but instead add the body class dark so the CSS will be i.e. body.dark .myselector {background-color: #000;}.

This is my attempt below to add the body class dark to the body tag, but of course, it doesn't work. I'm trying to use document.body.className and document.body.className.replace. How can I get this to work?

(function() {
  var darkSwitch = document.getElementById("darkSwitch");
  if (darkSwitch) {
    initTheme();
    darkSwitch.addEventListener("change", function(event) {
      resetTheme();
    function initTheme() {
      var darkThemeSelected =
        localStorage.getItem("darkSwitch") !== null &&
        localStorage.getItem("darkSwitch") === "dark";
      darkSwitch.checked = darkThemeSelected;
      darkThemeSelected
        ? document.body.className("dark")
        : document.body.className.replace("dark","");
    function resetTheme() {
      if (darkSwitch.checked) {
        document.body.className("dark");
        localStorage.setItem("darkSwitch", "dark"); 
} else {
        document.body.className.replace("dark","");
        localStorage.removeItem("darkSwitch");  
})();
                I think you'd want something closer to ? document.body.className = "dark"    : document.body.className = document.body.className.replace("dark","");  However, when doing a replacement, I think it's easier to use classList.remove();
– mykaf
                Nov 2, 2020 at 18:00
                Instead of document.body.className = document.body.className.replace("dark","");, I would use document.body.classList.remove("dark");  The former would also replace any partial matches. For example, class="darkPage" would become class="Page". className simply treats it as a string, while classList handles the list aspect.
– mykaf
                Nov 2, 2020 at 18:43
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.