Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS - v-bind:style + hover

Tags:

vue.js

vuejs2

I need to use CSS hover with VueJS v-bind:style directive but couldn't find information regarding it.

I need to bind styles for hover but v-bind:style.hover={} doesn't work. All the properties are going to be fetched from back-end, so I need to bind styles dynamically.

Are there other ways to bind styles on mouse over or CSS hover using VueJS?

Here is my code

This is the object :

button: {     colorBackd: '#1e2021',     colorBackdHover: '#000000',     text: 'Results',     color: '#d3e0ff',     colorHover: "#ffffff",     borderColor: '#d3e0ff',     borderColorHover: "#ffffff" }, 

Here is the html element that needs to be bound with styles

<button type="button"     :style="{     color:button.color,         backgroundColor:button.colorBackd,         borderColor:button.borderColor,     }"     class="btn btn-outline-info large-button">          {{ button.text }}  </button> 

Thanks

like image 233
dav88dev Avatar asked Oct 03 '17 19:10

dav88dev


1 Answers

Improved solution: use CSS custom properties and variables

If you only intend to work with modern/evergreen browsers, then using CSS custom properties and variables is the way to go! You can actually pass CSS custom properties into the :style binding, e.g.

computed: {   styleObject: function() {     return {       '--color': this.button.color,       '--color-hover': this.button.colorHover     }   } } 

And in your template:

<custom-button :style="styleObject" /> 

For the CSS, it's just a matter of:

button {   color: var(--color); }  button:hover {   color: var(--color-hover); } 

The advantage of this method is that you can scope CSS custom properties, so these variables will only apply to your specific button component when you define the CSS properties at the element level (instead of in :root).

The only drawback is that you have to iteratively declare all the variables in both hover and unhovered states, which can be a little bit cumbersome. However, I see this is a very minor disadvantage, compared to the benefits that you reap from using CSS variables.

See proof-of-concept below:

var customButton = Vue.component('custom-button', {    template: '#custom-button',    data() {      return {        button: {          colorBackd: '#1e2021',          colorBackdHover: '#000000',          text: 'Results',          color: '#d3e0ff',          colorHover: "#ffffff",          borderColor: '#d3e0ff',          borderColorHover: "#ffffff"        }      };    },    computed: {      styleObject() {        return {          '--button-color': this.button.color,          '--button-background-color': this.button.colorBackd,          '--button-border-color': this.button.borderColor,                    '--button-color--hover': this.button.colorHover,          '--button-background-color--hover': this.button.colorBackdHover,          '--button-border-color': this.button.borderColorHover        };      },    },  });    new Vue({    el: '#app'  });
button {    color: var(--button-color);    background-color: var(--button-background-color);    border-color: var(--button-border-color);  }    button:hover {    color: var(--button-color--hover);    background-color: var(--button-background-color--hover);    border-color: var(--button-border-color--hover);  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>  <div id="app">    <custom-button></custom-button>  </div>    <script type="text/template" id="custom-button">    <button type="button" :style="styleObject" class="btn btn-outline-info large-button">          {{ button.text }}    </button>  </script>

Original sotluion: use JS-based mouse events

You can store the hovered state of the element in its data, say hoverState. It is set to false by default, and is toggled to true when @mouseenter is fired, and back to false when @mouseleave is triggered:

Then, you can simply bind a computed property to the style attribute, for example, styleObject. In this styleObject, you can return the correct CSS styles depending on the hoverState found in the component's data:

var customButton = Vue.component('custom-button', {    template: '#custom-button',    data() {      return {        button: {          colorBackd: '#1e2021',          colorBackdHover: '#000000',          text: 'Results',          color: '#d3e0ff',          colorHover: "#ffffff",          borderColor: '#d3e0ff',          borderColorHover: "#ffffff"        },        hoverState: false      };    },    computed: {      styleObject() {        var modifier = '';        if (this.hoverState)          modifier = 'Hover';                  return {          color: this.button['color' + modifier],          backgroundColor: this.button['colorBackd' + modifier],          borderColor: this.button['borderColor' + modifier]        };      },    },    methods: {      updateHoverState(isHover) {        this.hoverState = isHover;      }    }  });    new Vue({    el: '#app'  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>  <div id="app">    <custom-button></custom-button>  </div>    <script type="text/template" id="custom-button">    <button type="button" :style="styleObject" @mouseenter="updateHoverState(true)" @mouseleave="updateHoverState(false)" class="btn btn-outline-info large-button">          {{ button.text }}    </button>  </script>
like image 67
Terry Avatar answered Sep 22 '22 06:09

Terry