Search code examples
javascripthtmljquerycsscss-variables

Set CSS variable in JS only for tag with attribute


I have an app that is in light mode and dark mode. I would like to dynamically set a variable for dark mode only. The issue I'm currently having is the dynamic variable is being set for both light mode and dark mode.

Here is an example:

$('#theme-btn').on('click', function() {
  //simple check if light then turn dark, and vice-versa 
  if($('html').attr('theme') === 'light') {
    $('html').attr('theme', 'dark');
  } else {
    $('html').attr('theme', 'light');
  }
})

$('#change-dark').on('click', function() {

  //set new dark mode primary color
  let dark_color = "#FF48C9"
    $("html[theme='dark']").get(0).style.setProperty("--primary", dark_color);

})
html[theme="light"] {
  --primary: #f6f6f6;
}

html[theme="dark"] {
  --primary: #121212;
}

.background {
  background: var(--primary);
  width: 100%;
  height: 60px;
  margin-bottom: 14px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html theme="light">
<body>

<div class="background"></div>

<button id="theme-btn">Change theme</button>
<button id="change-dark">Dynamically change dark mode color</button>

</body>
</html>

To test:

  1. Click on Change theme button several times.
  2. When on light mode, try clicking Dynamically change dark mode color.. Error should occur
  3. Next, change to dark mode, now click Dynamically change dark mode color.. Dynamic variable gets set.
  4. Change to light mode, and dynamic variable is set for both light and dark mode...

How can I get the dynamic variable to ONLY change for dark mode.

If anyone has any ideas, that would be great. Thank you.


Solution

  • You can use a second CSS custom property, one which gets adjusted when the button is clicked, and have --primary use either that custom property (if it's valid) - or, if not valid, the original color (of #121212):

    html[theme="light"] {
      --primary: var(--primary-light-custom, #f6f6f6);
    }
    
    html[theme="dark"] {
      --primary: var(--primary-dark-custom, #121212);
                  /*   ^^^ used if valid     ^^^^^^ fallback value */
    }
    
    $("html").get(0).style.setProperty("--primary-dark-custom", dark_color);
    

    $('html').attr('theme', 'light'); // to properly emulate your markup
          // in this Stack Snippet
    
    $('#theme-btn').on('click', function() {
      //simple check if light then turn dark, and vice-versa 
      $('html').attr('theme',
        $('html').attr('theme') === 'light' ? 'dark' : 'light'
      );
    })
    
    $('#change-dark').on('click', function() {
      //set new dark mode primary color
      let dark_color = "#FF48C9"
      $("html").get(0).style.setProperty("--primary-dark-custom", dark_color);
    
    })
    html[theme="light"] {
      --primary: var(--primary-light-custom, #f6f6f6);
    }
    
    html[theme="dark"] {
      --primary: var(--primary-dark-custom, #121212);
    }
    
    .background {
      background: var(--primary);
      width: 100%;
      height: 60px;
      margin-bottom: 14px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="background"></div>
    
    <button id="theme-btn">Change theme</button>
    <button id="change-dark">Dynamically change dark mode color</button>