2

I am new to jS and trying some simple tasks but even these so-called simple tasks are proving difficult at times. Please help me understand why this doesn't work. This snippet is to change style sheets by using a toggle. As you can probably work out.

I have two style sheets, a toggle (checkbox) and a function with an if else statement. Why can I not get this to work? Thank you

function toggleTheme() {

  let theme = document.getElementsByTagName('link')[0];

  if (theme.getAttribute('href') == 'darkstyle.css') {
    theme.setAttribute('href', 'lightstyle.css');
  } else {
    theme.setAttribute('href', 'darkstyle.css');
  }
}
<link rel="stylesheet" href="darkstyle.css" />

<link rel="stylesheet" href="lightstyle.css" />

<label class="switch">
  <input  type="checkbox" />
  <span onchange="toggleTheme()" class="slider round"></span>
</label>
Barmar
  • 741,623
  • 53
  • 500
  • 612
stee1e
  • 27
  • 5
  • When you have multiple stylesheets that define conflicting styles, the last one takes precedence. – Barmar Feb 15 '22 at 23:44
  • 1
    You should put the `onChange` in the `` tag .. – Zak Feb 15 '22 at 23:45
  • 1
    The usual way to do themes is to swap a class on the `` element, e.g. `class="dark"` and `class="light"`. Then use a single stylesheet that defines the styles of the classes. – Barmar Feb 15 '22 at 23:46
  • 1
    You would probably find a solution in this thread: https://stackoverflow.com/questions/19844545/replacing-css-file-on-the-fly-and-apply-the-new-style-to-the-page – legendofawesomeness Feb 15 '22 at 23:50
  • @legendofawesomeness cheers, I'll have a read of that thread. – stee1e Feb 16 '22 at 00:10

2 Answers2

4
  1. You've put an onchange listener onto a span element. A span element doesn't change. This listener should be on the checkbox.

  2. You should be changing the href of the second <link> tag, which would have an index of 1. The second one always overrides the first one.

  3. Small thing, but you don't need an else statement. Just return out of your if statement, then put your logic for the else under the if statement.

  4. You don't need two link tags for this use case.

  5. As someone already commented, this is a really weird way to toggle themes. Just have a single stylesheet, and toggle the theme on the body tag with a class.

<link rel="stylesheet" href="lightstyle.css" />

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

<script>
    function toggleTheme() {
        let theme = document.getElementsByTagName('link')[0];

        if (theme.getAttribute('href') === 'darkstyle.css') {
            return theme.setAttribute('href', 'lightstyle.css');
        }
        theme.setAttribute('href', 'darkstyle.css');
    }
</script>
mstephen19
  • 1,733
  • 1
  • 5
  • 20
1

Another option if you are interested:

<link type="text/css" rel="stylesheet" class="theme light" href="data:text/css;base64,Ym9keSB7IGJhY2tncm91bmQtY29sb3I6IGxpZ2h0Z3JheSB9"> <!--- Replace url with lightsyle.css --->
<link type="text/css" rel="stylesheet" class="theme dark" href="data:text/css;base64,Ym9keSB7IGJhY2tncm91bmQtY29sb3I6IGJsYWNrIH0=" disabled> <!--- Replace url with darkstyle.css --->

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

<script>
    function toggleTheme() {
        for (let style of document.querySelectorAll('link.theme') /* make sure that only theme styles are toggled */) {
            style.disabled = !style.disabled; //This will disable/enable the styles
        }
    }
</script>
ErrorGamer2000
  • 295
  • 3
  • 8
  • Sorry, I just put base64 urls so that you could see the example with a `link` element, not a `style` element. You need only change them. Also, the `light` and `dark` classes are purely semantic. The `light` theme makes the bacground lightgray while the `dark` theme makes it black. – ErrorGamer2000 Feb 16 '22 at 00:27