Any ideas why this dark mode switch isn't working?

My setup works great on my other apps (hand-coded, not built on Bubble), and I can’t figure out why it’s not working in my bubble app. Would love any advice you might have.

There’s 3 simple pieces to make this Dark/Light Mode switch:

  1. CSS to set all the color variables
/* Dark / Lite Mode */
@media screen and (prefers-color-scheme: light) {
    body {
        --color_bTHXV_default: rgba(23,29,37,1); 
        --color_text_default: rgba(23,29,37,1);
        --color_bTHXW_default: rgba(31,40,50,1); 
        --color_bTHXX_default: rgba(70,83,104,1); 
        --color_bTHXY_default: rgba(180,192,208,1); 
        --color_bTHXZ_default: rgba(242,244,247,1); 
        --color_bTHXa_default: rgba(255,255,255,1); 
    }

    body.dark-theme {
        --color_bTHXV_default: rgba(255,255,255,1);
        --color_text_default: rgba(255,255,255,1);
        --color_bTHXW_default: rgba(242,244,247,1);
        --color_bTHXX_default: rgba(180,192,208,1);
        --color_bTHXY_default: rgba(70,83,104,1);
        --color_bTHXZ_default: rgba(31,40,50,1);
        --color_bTHXa_default: rgba(23,29,37,1);
    }
}

@media screen and (prefers-color-scheme: dark) {
    body {
        --color_bTHXV_default: rgba(255,255,255,1);
        --color_text_default: rgba(255,255,255,1);
        --color_bTHXW_default: rgba(242,244,247,1);
        --color_bTHXX_default: rgba(180,192,208,1);
        --color_bTHXY_default: rgba(70,83,104,1);
        --color_bTHXZ_default: rgba(31,40,50,1);
        --color_bTHXa_default: rgba(23,29,37,1);
    }

    body.dark-theme {
        --color_bTHXV_default: rgba(23,29,37,1); 
        --color_text_default: rgba(23,29,37,1);
        --color_bTHXW_default: rgba(31,40,50,1); 
        --color_bTHXX_default: rgba(70,83,104,1); 
        --color_bTHXY_default: rgba(180,192,208,1);
        --color_bTHXZ_default: rgba(242,244,247,1); 
        --color_bTHXa_default: rgba(255,255,255,1); 
    }
}
  1. Javascript
const currentTheme = localStorage.getItem("theme");
if (currentTheme == "dark") {
  document.body.classList.add("dark-theme");
}

function changeToDarkMode(settings) {
    document.body.classList.toggle("dark-theme");

    let theme = "light";
    if (document.body.classList.contains("dark-theme")) {
      theme = "dark";
    }
    localStorage.setItem("theme", theme);
}
  1. Onclick event attached to an icon to make the switch:
changeToDarkMode();

Both #1 and #2 are placed in the header of my bubble app through the Settings > SEO/Metadata page. For #3 I’m using the Toolbox plugin to execute the onclick event.

It works fine in switching the color scheme when on the page, but it’s not persistent. As soon as you navigate to a different page, it reverts to the original theme (based on your system preference). The localStorage item is there, but for some reason it’s just not doing what it’s supposed to be doing.

Any ideas?

Your script is in the header, when it’e executed there is no body yet because the browser it’s still parsing and evaluating what’s in the header.
Ideally you want that script right after the opening body tag.
As an alternative you can use a mutation observer or more easily add a listener for DOMContentLoaded event and execute your logic when the event is triggered. Either way you want to wait for the existence of the body.

Another even easier solution is to add that class to the html element itself and use document.documentElement.toggle("dark-theme").

2 Likes

Oh gosh… what an obvious mistake! lol thank you so much @dorilama! That was it. Just needed to place the script in the Body. :clap:

2 Likes

This topic was automatically closed after 70 days. New replies are no longer allowed.