3

So, I have a button that toggles between dark and light mode (my site is dark by default) and it works but now I need it to stay on whatever toggle state is selected across multiple pages. I suspect it has something to do with sessionstorage. Not using jQuery and don't want to. What can I just add to my code to make that happen?

I have five pages all linked to styles.css with an id of "dark" and then in the JS I'm referencing a second style sheet, light.css or 'light' in the JS, so I'm toggling the style sheets. All five pages have the button in the footer each with the same function written in one JS file.

HTML

<head>
<link rel="stylesheet" href="styles.css" id="dark">
</head>

<body>
<button onclick="toggle();" id="light-mode"><i class="fas fa-adjust"></i></button>
</body>

JavaScript

function toggle() {
    var a = document.getElementById("dark");
    a.x = 'light' == a.x ? 'styles' : 'light';
    a.href = a.x + '.css';
}

This works perfectly, just not sure how to integrate sessionstorage or localstorage to save the toggle state across the site. What is the best method proceeding from this point if possible or should I do a complete overhaul?

UPDATE

So, tried @Reality's answer and not working but I think I might just be integrating it wrong. Very new to JS.

localStorage.setItem('toggled','true');

function toggle() {
    var a = document.getElementById("dark");
    a.x = 'light' == a.x ? 'styles' : 'light';
    a.href = a.x + '.css';

    if (localStorage.getItem('toggled') === 'false') {
        localStorage.setItem('toggled','true');
    } else {
        localStorage.setItem('toggled','false');
    }
}

SOLVED

Ok, anyone wanting to know how to toggle a theme perfectly where it works across your website, just follow this: https://dev.to/albertomontalesi/add-dark-mode-to-your-website-with-just-a-few-lines-of-code-5baf

When you follow that, you should do an additional thing to have your theme load better when toggled to. Just link to your second style sheet in the head of every page and add disabled="disabled" If you don't add this to the above approach, I found that when toggling to whatever theme and then navigating around the site, you basically have to load a new style sheet and you get a flicker and can even see the bare HTML version of the site momentarily, so this addition fixes that because by putting it in the head it is already loaded from the beginning.

FINAL

Here's what ended up working:

    <head>
        <link rel="stylesheet" href="dark-theme.css" type="text/css" id="theme">
        <link rel="stylesheet" href="light-theme.css" type="text/css" disabled="disabled">
        <script>
            document.addEventListener('DOMContentLoaded', () => {
                const themeStylesheet = document.getElementById('theme');
                const storedTheme = localStorage.getItem('theme');
                    if (storedTheme) {
                        themeStylesheet.href = storedTheme;
                    }
                const themeToggle = document.getElementById('theme-toggle');
                themeToggle.addEventListener('click', () => {
                    if (themeStylesheet.href.includes('dark')) {
                        themeStylesheet.href = 'light-theme.css';
                    } else {
                        themeStylesheet.href = 'dark-theme.css';
                    }
                    localStorage.setItem('theme', themeStylesheet.href);
                });
            });
        </script>
    </head>

Per @Reality's suggestion, placing the JS in the head improved performance better than what the SOLVED edit suggested doing, however, the code in the link provided (https://dev.to/albertomontalesi/add-dark-mode-to-your-website-with-just-a-few-lines-of-code-5baf) is what is used in the above example. Still needed the disabled="disabled" in the light-theme.css link or else it would override the dark-theme.css and the toggle wouldn't occur all together. This was true of all the code examples seen in this thread that were tried.

  • 1
    I think this may give you some direction - https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage – Zack Macomber Nov 02 '20 at 20:11
  • Does this answer your question? [Persist variables between page loads](https://stackoverflow.com/questions/29986657/persist-variables-between-page-loads) – Heretic Monkey Nov 02 '20 at 20:29
  • ALSO `disabled="disabled"` prevents the second style sheet from overriding your "default" one and ruining the toggle effect. –  Nov 03 '20 at 00:17
  • Just put the javascript in the head. That way it executes it before the page loads, preventing the flickering (because head loads before body). – Reality Nov 03 '20 at 14:34
  • That works too. I prefer keeping everything (html, css, js) separate so its preference. –  Nov 03 '20 at 16:01
  • JS in the head performed better than what I suggested so that's the way to go. –  Nov 04 '20 at 03:28

1 Answers1

3

You can set it using localStorage.setItem(); and localStorage.getItem().

localStorage.setItem('toggled','true');
//or
localStorage.setItem('toggled','false');

inside your toggle function:

//get the style by it's id
let a = document.getElementById("dark");
if(localStorage.getItem('toggled') === 'false'){
   //set toggled to true, because the user clicked it when dark theme is on
   localStorage.setItem('toggled','true');
   //toggled is now on, in this case, light theme is switched on
   //do something here
   a.href = "light.css";
}
else{
   //set toggled to false, because the user clicked it when light theme is on
   localStorage.setItem('toggled','false');
   //if toggled is off, in this case, dark theme is switched on
   a.href = "styles.css";
}

It seems confusing at first, but just pay attention to the logic. It'll start to unfold in your mind as you read and reread it :) If you want to switch to session storage (for that tab instance. Once you close the tab, session storage for that tab is deleted), then just replace the "localStorage" with "sessionStorage". Please keep in mind that localStorage and sessionStorage stringify values (convert them into a string) before storing them.

Reality
  • 637
  • 1
  • 6
  • 25
  • Does this just go under everything already in the toggle function? So far not working but I think it's b/c I might be integrating it wrong. Very new to JS. Can you show your example with my code included, like how you're adding it? –  Nov 02 '20 at 21:29
  • You just add it into the your function. It should work (if not, just tell me). I added comments. Inside the if-else statement, put your code that switches to dark mode inside the else statement, and the code that switches to light mode inside of the if statement (btw, very clever way of light-dark mode) – Reality Nov 03 '20 at 14:21
  • Just copy and paste the code into your toggle function (ignore the long comment I made two posts above). If it doesn't work, tell me. – Reality Nov 03 '20 at 14:40