7

I want to access the values of css root variables in the project in a Vue component. For example, change the 10 variables, including the color, margin, and font size, by pressing a button to the new values, and then pressing the same button to change the variables to their ( default ) original values, in fact changing the values of the css root variables in the project. How can I do this ? In fact, I want to switch between dark and light by pressing a button.

This idea is inspired by the changes from the link below. The example inside the link is written in the pure JavaScript script, and I want to use it in the Vue project that develope on Next Js Framework . To implement a website with about 10 variables whose values must change immediately with pressing a button to toggling in the dark / light mode.

The codepen link that inspired me :)

How can I access and change Css root variables?

new Vue({
	el: "#theme",
	data: {
    return {
      dark: true,
      
    };
  },
  
  watch: {
    dark() {
    
      let bg = this.dark ? "#1b1b1b" : "#f5f5f5";
      let txtColor = this.dark ? "#999999" : "#333333";
      
      document.documentElement.style.setProperty("--bg", bg);
      document.documentElement.style.setProperty("--txt", txtColor);
      
    }
  }
});
:root{

--bg: white;
--txt: black;

}


body {
  background-color: var(--bg);
  color: var(--txt)
}
article {
  padding: 50px
}
article h2 {
  margin-top: 100px;
}
<div id="theme">

  <button @click="dark=!dark">dark</button>

<article>
  <h1>Hello World</h1>
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean v
</article>

</div>

1 Answer 1

11

You have a syntax error at data in your example but aside from that it works OK. Did you want to run as soon as the page loads?

new Vue({
  el: "#theme",
  data() {
    return {
      dark: false,
      root: null
    };
  },
  mounted: function() {
    this.root = document.documentElement;
  },
  watch: {
    dark: {
      handler: function() {
        // because we are using this handler immideatly we need to wait for data changes using nextTick.
        this.$nextTick(() => {
          if (this.dark) {
            this.root.style.setProperty("--bg", "red");
            this.root.style.setProperty("--text", "black");
            this.root.style.setProperty("--padding", "10px");
            this.root.style.setProperty("--font", "1rem");
          } else {
            this.root.style.setProperty("--bg", "blue");
            this.root.style.setProperty("--text", "green");
            this.root.style.setProperty("--padding", "15px");
            this.root.style.setProperty("--font", "2rem");
          }
        })
      },
      immediate: true

    }
  }
});
:root {
  --bg: white;
  --bg-text: black;
  --padding: 5px;
  --font: 3rem;
}

body {
  background-color: var(--bg);
  color: var(--bg-text)
}

article {
  padding: 50px
}

article h2 {
  margin-top: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="theme">

  <button @click="dark=!dark">dark</button>

  <article>
    <h1>Hello World</h1>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis,
    sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus.
    Vivamus elementum semper nisi. Aenean v
  </article>

</div>

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

10 Comments

Yes, the bright mode will be displayed in the initial load.
I have updated my answer. You need to add handler and immediate properties to watch. Also, set dark to false
Thanks, between this solution and the next answer solution , which one has better performance?
I am not sure about performance. My guess that it won't make much difference if you have few changes. You can use computed instead of watch if you want vuejs to cache the values.
It nuxt js Framework gives an error when running, error text : ReferenceError document is not defined
|

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.