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:
JavaScript
x
15
15
1
[
2
{
3
id: 13241243,
4
color: "#123456",
5
activeColor: "#abcdef",
6
text: "Asadpyqewri"
7
},
8
{
9
id: 742378104,
10
color: "#234567",
11
activeColor: "#bcdefa",
12
text: "Iudaofqepr"
13
}
14
]
15
Menu looks like:
JavaScript
1
6
1
<v-btn-toggle>
2
<v-btn v-for="item in items" :key="item.id" :color="item.color">
3
{{item.text}}
4
</v-btn>
5
</v-btn-toggle>
6
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.
JavaScript
1
8
1
mounted(){
2
window.onload = function(){
3
const targetNodes = document.getElementsByClassName('asdff');
4
var a = targetNodes.item(0);
5
//"targetNodes" is a HTMLCollection with 3 elements, but "a" is null.
6
}
7
}
8
- 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
JavaScript
1
28
28
1
Vue.component('pseudo', {
2
data() {
3
return {
4
msg: 'Hover on me',
5
}
6
},
7
props: {
8
color: {
9
type: String,
10
},
11
text: {
12
type: String,
13
}
14
},
15
computed: {
16
cssAttrs() {
17
return {
18
'--color': this.color,
19
'--text': JSON.stringify(this.text),
20
}
21
}
22
},
23
template: `<button class="content" :style="cssAttrs">{{msg}}</button>`,
24
});
25
26
var vm = new Vue({
27
el: '#app',
28
});
JavaScript
1
7
1
.content {
2
color: red;
3
}
4
.content:focus {
5
content: var(--text);
6
color: var(--color);
7
}
JavaScript
1
4
1
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
2
<div id="app">
3
<pseudo color="blue" text="Changing!!"></pseudo>
4
</div>