52
votes

Is it possible to add the dynamic variable in style?

I mean something like:

<style>
 .class_name{
  background-image({{project.background}});
 }
@media all and (-webkit-min-device-pixel-ratio : 1.5),
 all and (-o-min-device-pixel-ratio: 3/2),
 all and (min--moz-device-pixel-ratio: 1.5),
 all and (min-device-pixel-ratio: 1.5) {
 .class_name{
  background-image({{project.background_retina}});
 } 
}
</style>
8
CSS is static. If your style is really complex, maybe you will need some CSS pre-processor.Illuminator

8 Answers

36
votes

The best way to include dynamic styles is to use CSS variables. To avoid inline styles while gaining the benefit (or necessity—e.g., user-defined colors within a data payload) of dynamic styling, use a <style> tag inside of the <template> (so that values can be inserted by Vue). Use a :root pseudo-class to contain the variables so that they are accessible across the CSS scope of the application.

Note that some CSS values, like url() cannot be interpolated, so they need to be complete variables.

Example (Nuxt .vue with ES6/ES2015 syntax):

<template>

<div>
  <style>
    :root {
      --accent-color: {{ accentColor }};
      --hero-image: url('{{ heroImage }}');
    }
  </style>
  <div class="punchy">
    <h1>Pow.</h1>
  </div>
</div>

</template>
<script>

export default {
  data() { return {
    accentColor: '#f00',
    heroImage: 'https://vuejs.org/images/logo.png',
  }},
}

</script>
<style>

.punchy {
  background-image: var(--hero-image);
  border: 4px solid var(--accent-color);
  display: inline-block;
  width: 250px; height: 250px;
}
h1 {
  color: var(--accent-color);
}

</style>

Also created an alternate more involved runnable example on Codepen.

34
votes

I faced the same problem.I have been trying to use background color value from database.I find out a good solution to add a background color value on inline css which value I set from database.

<img  :src="/Imagesource.jpg" alt="" :style="{'background-color':Your_Variable_Name}">
9
votes

As you are using vuejs, Use vuejs to change background instead css

var vm = new Vue({
  el: '#vue-instance',
  data: {
    rows: [
      {value: 'green'},
      {value: 'red'},
      {value: 'blue'},
    ],
    item:""
  },
  methods:{
  	  onTimeSlotClick: function(item){
         console.log(item);
      	document.querySelector(".dynamic").style.background = item;
      }

  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.16/vue.js"></script>
<div id="vue-instance">
   <select class="form-control" v-model="item" v-on:change="onTimeSlotClick(item)">
         <option value="">Select</option>
        <option v-for="row in rows">
          {{row.value}}
        </option>
      </select>
      <div class='dynamic'>VALUE</div>
      <br/><br/>
      <div :style="{ background: item}">Another</div>
</div>
8
votes

CSS <style> is static. I don't think you can do that... you might have to look for a different approach.

You can try using CSS variables. For example, (code below is not tested)

<template>
  <div class="class_name" :style="{'--bkgImage': 'url(' + project.background + ')', '--bkgImageMobile': 'url(' + project.backgroundRetina + ')'}">
  </div>
</template>

<style>
  .class_name{
      background-image: var(--bkgImage);
  }
  @media all and (-webkit-min-device-pixel-ratio : 1.5),
     all and (-o-min-device-pixel-ratio: 3/2),
     all and (min--moz-device-pixel-ratio: 1.5),
     all and (min-device-pixel-ratio: 1.5) {
        .class_name{
            background-image: var(--bkgImageMobile);
        } 
  }
</style>

Note: Only latest browsers support CSS Variables.

UPDATE:

If you still see any issues with the :style in the template then try this,

<div :style="'--bkgImage: url(' + project.background + '); --bkgImageMobile: url(' + project.backgroundRetina + ')'">
</div>
4
votes

Late to the party here, but yes, this is possible. Vue does not support style tags in templates, but you can get around this by using a component tag. Untested pseudo-code:

In your template:

<component type="style" v-html="style"></component>

In your script:

props: {
    color: String
}
computed: {
    style() {
        return `.myJSGeneratedStyle { color: ${this.color} }`;
    }
}

There are lots of reasons why you shouldn't use this method, it's definitely hacky and :style="" is probably better most of the time, but for your problem with media queries I think this is a good solution.

2
votes

I encountered the same problem and I figured out a hack which suits my needs (and maybe yours).

As <style> is contained in <head>, there is a way to make it work:

We generate the css as a computed property based on the state of the page/component

computed: {
    css() {
        return `<style type="text/css">
         .bg {
            background: ${this.bg_color_string};
         }</style>`
    }
}
 

Now, we have our style as a string and the only challenge is to pass it to the browser.

I added this to my <head>

<style id="customStyle"></style>

Then I call the setInterval once the page is loaded.

 mounted() {
     setInterval(() => this.refreshHead(), 1000);
 }

And I define the refreshHead as such:

methods: { 
   refreshHead() {
       document.getElementById('customStyle').innerHTML = this.css
   }
}
2
votes

You can use the component tag offered by vue.

<template> 
  <component :is="`style`"> 
    .cg {color: {{color}};} 
  </component> 
  <p class="cg">I am green</p> <br/>
  <button @click="change">change</button>
</template> 
<script> 
  export default { 
    data(){ 
      return { color: 'green' }
    },
    methods: {
      change() {this.color = 'red';}
    }
  } 
</script>
1
votes

In simple this is how you would do in Vue/nuxt.

<template>
 <div>
    <img  :src="dynamicImageURL" alt="" :style="'background-color':backgroundColor"/>
</div>
</template>

<script>
export default{
    data(){
       return {
             dynamicImageURL='myimage.png',
             backgroundColor='red',
        }
    }
}
</script>