3

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?

Origami1024
  • 157
  • 3
  • 11
  • You can't manipulate pseudo elements with javascript, since they are not part of the DOM. what you should do is, use e different class with the `pseudo` properties you need. and toggle that class to your target element with javascript – Towkir Oct 19 '19 at 14:32
  • @Towkir, but class would have predefined properties, and i want to take ANY color in props – Origami1024 Oct 19 '19 at 14:41
  • Right, can you elaborate your code a bit in detail, such as what does `--btnHoverBg` or `--wrapHoverbgcl` result into ? – Towkir Oct 19 '19 at 16:14
  • changed/included more code – Origami1024 Oct 19 '19 at 17:07
  • Alright, your script in the `mounted` doesn't make sense. `setProperty` will try to add a css property and value, but your variable refers to a css value, not a property. Also, this is not doable with inline css. – Towkir Oct 19 '19 at 17:28
  • @Towkir, I dont get what you mean "variable refers to css value, not property"? The code works. My question is that I want to know how to do it differently, how people who produce real vue projects generally do it. – Origami1024 Oct 19 '19 at 17:38
  • 1
    I believe you could use `:style="{'--wrapHoverColor': color1}"` to avoid the `mounted` hook. There are a few ways to do this if you don't mind having an extra element but I'm struggling to think of a better way that uses just the one element. – skirtle Oct 19 '19 at 19:28
  • @skirtle, with this I also don't need to declare some inner elements as refs. It simplifies my code nicely, thank you. – Origami1024 Oct 19 '19 at 20:07

1 Answers1

3

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>
Nainemom
  • 121
  • 6
  • this is nice, maybe in the part #1, its possible to incorporate skirtle's comment(under the question), to shorten the code and skip created hook – Origami1024 Dec 13 '19 at 13:51
  • this looks great but often we would want to use the default styles from the scss files & vars included. How could we safely use this method only when needed with safe fallback to the base css? – v3nt Apr 22 '21 at 10:37
  • Is it possible to achieve this with SASS as well? I've been trying with variables but no luck – pythonNovice Apr 28 '21 at 23:22