skip to Main Content

I have a dark-mode system built into my website but I can’t figure out how to switch the image source. I’m using the Javascript below with no problems for a bunch of other variables (mostly color but also element positions, etc), I just need to add something for the img src but I’m not sure what to do next.

Code

const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');

function switchTheme(e) {
  if (e.target.checked) {
    document.documentElement.setAttribute('data-theme', 'dark');
  } else {
    document.documentElement.setAttribute('data-theme', 'light');
  }
}

toggleSwitch.addEventListener('change', switchTheme, false);
<picture class="swoop">
  <source srcset="assets/landingContentSwoopDark.png">
  <img src="assets/landingContentSwoopWhite.png ">
</picture>

EDIT:

I tried the answer below with some changes for my particular case and it still isn’t working, but I’m guessing that’s due to what I changed. Here is the updated code:

<div class="theme-switch-wrapper col-md-3">
    <label class="theme-switch switch pull-right" for="checkbox">
        <input type="checkbox" id="checkbox">
        <span class="slider round"></span>
    </label>

<script>
    const image = document.querySelector('.swoopImage');
    const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');

    function switchTheme(e) {
        if (e.target.checked) {
            document.documentElement.setAttribute('data-theme', 'dark');
            image.src = 'assets/landingContentSwoopDark.png';
        }
        else {
            document.documentElement.setAttribute('data-theme', 'light');
            image.src = 'assets/landingContentSwoopWhite.png';
        }
    }

    toggleSwitch.addEventListener('change', switchTheme, false);
    </script>
</div>

and

<div class="swoop">
    <img style="margin-top: -53%; position: relative; pointer-events: none;" class="swoopImage" src="assets/landingContentSwoopWhite.png" alt="image">
</div>

2

Answers


  1. Problem

    Given your code, I think it’s because of the use of picture tag as it uses the first one if possible else it falls back to the next ones, and since your first image works it does not goes to next one. And then to switch the images you are changing the --bg-swoop variable through which you wanted to switch background image (I assume) but that’s not how this works. To change the source of the image you need to use JS to change the value in src of the image.

    Solution

    There are some vague places. SO assuming you want to just swap the image based on Toggle dark mode, you can use the following:

    if (toggle.checked) {
        image.src = 'path/to/image-on-check.png';
    } else {
        image.src = 'path/to/image-on-un-check.png';
    }
    

    and as for HTML, you can only have a image tag:

    <img id="image" src="path/to/image-on-un-check.png" alt="Image">
    

    Demo

    const toggle = document.getElementById('toggle');
    const image = document.getElementById('image');
    
    toggle.addEventListener('change', () => {
      if (toggle.checked) {
        image.src = 'https://repository-images.githubusercontent.com/692536747/5f5045c4-56a9-4dfc-ab63-6605677a0711';
      } else {
        image.src = 'https://repository-images.githubusercontent.com/711272363/eed53990-6c00-421c-98ae-daf8590d9481';
      }
    });
    <label for="toggle">Toggle Image:</label>
    <input type="checkbox" id="toggle">
    
    <img id="image" src="https://repository-images.githubusercontent.com/711272363/eed53990-6c00-421c-98ae-daf8590d9481" alt="Image">

    For your case

    For your particular case, the code would be:

    const image = document.querySelector('.swoop');
    const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');
    
    function switchTheme(e) {
      if (e.target.checked) {
        image.src = 'assets/landingContentSwoopDark.png';
      } else {
        image.src = 'assets/landingContentSwoopWhite.png';
      }
    }
    
    
    toggleSwitch.addEventListener('change', switchTheme, false);
    
    <img class="swoop" src="assets/landingContentSwoopWhite.png" alt="Image">
    

    Hope that works.

    Login or Signup to reply.
  2. I would approach this quite differently than you are currently doing.

    I would have the page theme determined by which CSS classes are in use and then just toggle the CSS classes when the theme needs to be changed.

    When it comes to swapping images, I would set the image as a background on an element, rather than use picture or img because background images can be set with CSS.

    Here is an example:

    const themeImg = document.querySelector("div.img");
    
    document.querySelector(".themeWrapper").addEventListener("click", function(event){
      // event.target represents the radio button that initiated the event (got clicked)
      if(event.target.value === "dark"){
        // Just switch classes to change themes
        document.body.classList.remove("light");
        document.body.classList.add("dark");
        themeImg.classList.remove("light");
        themeImg.classList.add("dark");
      } else {
        document.body.classList.add("light");
        document.body.classList.remove("dark");
        themeImg.classList.add("light");
        themeImg.classList.remove("dark");
      }
    });
    /* Standard Styles */
    div.img {
      width:300px;
      height:200px;
      background-size: cover;
      background-repeat: no-repeat;
    }
    
    /* Default theme (light) */
    body.light {
      background: #fff;
      color: #000;
    }
    
    div.img.light { 
      background:url(https://png-3.vector.me/files/images/6/9/697797/acid_smiley_face_vector_free_preview.png);
    }
    
    /* Alternate theme (dark) */
    body.dark {
      background: #000;
      color: #fff;
    }
    
    div.img.dark { 
      background:url(https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQaTmuzhVLgp7J9I85SBrR29znZb2i0syZR1g&usqp=CAU);
    }
    <!doctype html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Themed Page</title>
    </head>
    <body class="light">
      <p>Choose a theme</p>
      <div class="themeWrapper">
        <input type="radio" name="theme" value="light" checked>Light &nbsp;&nbsp;&nbsp;
        <input type="radio" name="theme" value="dark">Dark
      </div>
    
      <div class="img light"></div>
    
    </body>
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search