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?
CodePudding user response:
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 :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>