Skip to content
Advertisement

Solved – Vue dynamically add style to :active pseudo class

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>
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement