Toggle CSS root variables with JavaScript or jQuery?

Viewed 2254

I'm trying my best to theme a website with CSS root variables and jQuery / Javascript.

:root {
 --color1: red;
 --color2: green;
 --background-color: var(--color1);
 --text-color: var(--color2);
}

When a button is clicked, I want to "toggle" both the background and text color css variables. The following example works well (just once, no toggle) - it just adds the given style properties to my html tag.

document.documentElement.style.setProperty('--background-color','var(--color2)');
document.documentElement.style.setProperty('--text-color','var(--color1)');

=> <html style="--text-color=var(--color1);--background-color=var(--color2);"

How could I make this to toggle to other "themes" when clicking the button after the initial click?

2 Answers

How about the following example. It just changes a class name but by doing so it also changes the colors.

const themed = document.getElementsByClassName('themed');

for( let theme of themed )
{
  theme.addEventListener('click', () => {
    theme.classList.toggle('theme1');
  });
}
:root {
  --color1: red;
  --color2: green;
  --background-color: var(--color1);
  --text-color: var(--color2);
}

.themed {
  background: var(--background-color);
  color: var(--text-color);
  padding: 10px;
  border: 0;
  font-weight: 700;
}

.theme1 {
  --background-color: var(--color2);
  --text-color: var(--color1);
}
<button class="themed">Example</button>

Or you can specify multiple "themes" and loop trough them:

const buttons = document.getElementsByTagName('button');
const themes = 4; // Specify amount of themes

for( let button of buttons )
{
  /*
    Set i to be equal to the theme number
    If theme1 is set i = 1, theme2 i = 2
  */
  let i = parseInt( button.classList[ 0 ].slice( -1 ) );
  button.addEventListener('click', () => {
    console.log(i);
    // Delete last set theme
    if(i === 1) {
      button.classList.remove(`theme${themes}`);
    } else {
      button.classList.remove(`theme${ i - 1}`);
    }
  
    // Set theme
    button.classList.add(`theme${i}`);
    
    // Reset i
    if( i === themes )
    {
      i = 1;
    } else {
      i++;
    }
  });
}
:root {
  --color1: red;
  --color2: green;
  --color3: blue;
  --color4: orange;
  --background-color: var(--color1);
  --text-color: var(--color2);
}

button {
  background: var(--background-color);
  color: var(--text-color);
  padding: 10px;
  border: 0;
  font-weight: 700;
}

.theme1 {
  --background-color: var(--color1);
  --text-color: var(--color2);
}

.theme2 {
  --background-color: var(--color2);
  --text-color: var(--color1);
}

.theme3 {
  --background-color: var(--color3);
  --text-color: var(--color4);
}

.theme4 {
  --background-color: var(--color4);
  --text-color: var(--color3);
}
<button class="theme1">Theme1</button>
<button class="theme4">Theme4</button>

You first have to get the root element using Document.documentElement and then just modify the css variables with style.setProperty :

let initialTheme = true;

function toggleColors() {   
  const root = document.documentElement;

  if(initialTheme) {
    root.style.setProperty('--background-color', 'green');
    root.style.setProperty('--text-color', 'red');
    initialTheme = false;  
  } else {
    root.style.setProperty('--background-color', 'red');
    root.style.setProperty('--text-color', 'green');
    initialTheme = true;
  }
}
:root {
 --background-color: red;
 --text-color: green;
}

.ct {
  background-color: var(--background-color);
}

p {
  color: var(--text-color);
}
<button onclick="toggleColors()">toggle</button>
<div class="ct">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis suscipit vestibulum nulla ut commodo. Donec et turpis facilisis quam vulputate vestibulum non quis turpis. Etiam leo eros, tempus vehicula magna vel, laoreet commodo elit. Pellentesque maximus vulputate faucibus. Praesent tempor, quam quis mollis dignissim, nisl felis luctus arcu, convallis vulputate erat magna in elit. Ut nec eros posuere, viverra dui et, interdum risus. Donec convallis felis ante, nec mattis lectus semper sed. Donec eget pellentesque nisi. Aliquam consequat eleifend elit vel dapibus.</p>
</div>

Related