:hover color in vue components from props

Viewed 2774

Some of my single-file components need to take hover color from props.

My solution is that i set css variables in the following way (the main part is in the mounted(){...})

<template>
    <div class="btnWrapper" ref="btnWrapper">...</div>
</template>
...
...
props() {
    color1: {type: String, default: 'blue'},
},
mounted () {
    this.$refs.btnWrapper.style.setProperty('--wrapHoverColor', this.color1)
}
...
...
<style scoped>
.btnWrapper {
    --wrapHoverColor: pink;
}
.btnWrapper:hover {
    background-color: var(--wrapHoverColor) !important;
}
</style>

This solution seems kind of woowoo. But maybe there is no better way with pseudo elements, which are hard to control from js. Do you guys ever take pseudo element's properties from props in vue components?

1 Answers

You have two different ways to do this.

1 - CSS Variables

As you already know, you can create CSS variables from what you want to port from JS to CSS and put them to your root element :style attr on your components created hooks, and then use them inside your CSS codes with var(--x).

<template>
<button :style="style"> Button </button>
</template>

<script>
export default {
  props: ['color', 'hovercolor'],
  data() {
    return {
      style: {
        '--color': this.color,
        '--hovercolor': this.hovercolor,
      },
    };
  }
}
</script>

<style scoped>
button {
  background: var(--color);
}
button:hover {
  background: var(--hovercolor);
}
</style>

2 - Vue Component Style

vue-component-style is a tiny (~1kb gzipped) mixin to do this internally. When you active that mixin, you can write your entire style section inside of your component object with full access to the component context.

<template>
<button class="$style.button"> Button </button>
</template>

<script>
export default {
  props: ['color', 'hovercolor'],
  style({ className }) {
    return [
      className('button', {
        background: this.color,
        '&:hover': {
          background: this.hovercolor,
        },
      });
    ];
  }
}
</script>
Related