3

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?

4
  • Can you specify what you mean with themes? Commented Oct 20, 2018 at 18:46
  • Ok, let's say there is --color1, --color2, --color3, --color4, ... I want to toggle through "background-color -> color1, text -> color2" -> "background -> color4, text -> color2" and so on. Right now it would be enough to just toggle the variables --background and --text to color1/color2 and vice versa (just the opposite direction). But how would I know when and to which value the variables should get changed? Commented Oct 20, 2018 at 18:47
  • The problem with that is that JS will never know what classes or variables are defined in CSS. So JS will never know where to start or stop unless you tell it to. So there is no way of making it completely dynamic Commented Oct 20, 2018 at 19:15
  • Updated the answer to be more dynamic Commented Oct 20, 2018 at 19:44

2 Answers 2

2

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>

Sign up to request clarification or add additional context in comments.

Comments

1

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>

2 Comments

How is this different to what the OP already has. I mean you just replaced the variables with the colors they represent.
It's what he wanted. Or at least what I understood from the question. To toggle the text color variable with the background color variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.