HIGHLIGHT: This is a solved problem.
Edit: Solved the problem using @Amaarockz’s advice!
I haven’t had much experience in CSS variables & complicated :style structures, but turned out they’re great!
Original question:
I have a menu built with Vue.js (and Vuetify), data passed in from the backend like:
[ { id: 13241243, color: "#123456", activeColor: "#abcdef", text: "Asadpyqewri" }, { id: 742378104, color: "#234567", activeColor: "#bcdefa", text: "Iudaofqepr" } ]
Menu looks like:
<v-btn-toggle> <v-btn v-for="item in items" :key="item.id" :color="item.color"> {{item.text}} </v-btn> </v-btn-toggle>
Problem
I want to know, how can I dynamically make the items in a different color when they have :active pseudo-class?
What I’ve tried:
- Write something in “style” attribute of list items:
- Failed, as I can’t add a selector in <element style=””>, only styles.
- Use an attribute like “active-color” defined by Vuetify:
- Failed, such things don’t exist.
- Dynamically add colors to the “v–btn-active” class, which Vuetify adds automatically:
- Failed, I can’t find a way to do this seperately for each button.
- Watch when the :active pseudo-class appears, add style in the listener:
- Somehow MutationObserver didn’t work for me.
- getElementsByClassName[0] keeps getting “null”. I tried writing that in windows.onload, nothing changed.
- One time it returned the correct node, and I was able to watch the class mutation. But I can’t reproduce that even though nothing changed in the code.
mounted(){ window.onload = function(){ const targetNodes = document.getElementsByClassName('asdff'); var a = targetNodes.item(0); //"targetNodes" is a HTMLCollection with 3 elements, but "a" is null. } }
- Add one different class to every button, and write seperate CSS for them using JavaScript:
- Perhaps doable, but code’s going to be extremely ugly & difficult to maintain.
- Besides, it’s hard to overwrite Vuetify’s default style outsides <element style>; you have to add !important.
Last two attempts are what I think more hopeful. Is there any way to work through?
Advertisement
Answer
Try using pseudo class like
Vue.component('pseudo', { data() { return { msg: 'Hover on me', } }, props: { color: { type: String, }, text: { type: String, } }, computed: { cssAttrs() { return { '--color': this.color, '--text': JSON.stringify(this.text), } } }, template: `<button class="content" :style="cssAttrs">{{msg}}</button>`, }); var vm = new Vue({ el: '#app', });
.content { color: red; } .content:focus { content: var(--text); color: var(--color); }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <pseudo color="blue" text="Changing!!"></pseudo> </div>