Vue.js dynamic <style> with variables

Cssvue.jsVuejs2

Css Problem Overview


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>

Css Solutions


Solution 1 - Css

I faced the same problem. I have been trying to use a background color value from a 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}">

Solution 2 - Css

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.

Solution 3 - Css

With Vue.js 3.2 you can do State-Driven Dynamic CSS like this:

<template>
    <h1 id="script">Script</h1>
    <h1 id="scriptSetup">Script setup</h1>
</template>

<script>
  export default {
    data() {
      return {
        colorFromScript: 'red'
      }
    }
  }
</script>

<script setup>
const colorFromScriptSetup = 'green'
</script>

<style>
  #script {
      color: v-bind('colorFromScript')
  }

  #scriptSetup {
      color: v-bind('colorFromScriptSetup')
  }
</style>

See an implementation here

Solution 4 - Css

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, (the 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 the latest browsers support CSS variables.

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>

Solution 5 - Css

As you are using Vue.js, use Vue.js to change the background, instead of 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>

Solution 6 - Css

Yes, this is possible. Vue.js does not support style tags in templates, but you can get around this by using a component tag. Untested pseudocode:

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.

Solution 7 - Css

You can use the component tag offered by Vue.js.

<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';}
    }
  }

Solution 8 - Css

Vue 3 State-Driven Dynamic CSS Variables

I know this is a bit late and is using Vue.js 2, but as of now in Vue.js 3 you can create state-driven CSS variables.

You can now use your SFC (Single File Component) state data inside your styles tags using v-bind().

You can read more about state-driven CSS variables here, or read the Vue.js 3 documentation here.

Here is a code example

Example
<template>
  <div>
    <input type="text" v-model="color" />
    <div class="user-input-color">
      {{ color }}
    </div>
  </div>
</template>

<script>
export default {
  data: () => ({
    color: 'white'
  })
}
</script>

<style scoped>
.user-input-color {
  background-color: v-bind(color)
}
</style>

Here is a link to the live example.

Links

Solution 9 - Css

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 content 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
   }
}

Solution 10 - Css

In simple terms, this is how you would do it in Vue.js and Nuxt.js:

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

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

Solution 11 - Css

I needed to write completely dynamic styles, so I used approach beyond Vue system:

{
   // Other properties.
    watch: {
        myProp: {
            handler() {
                this.styleElement.innerHTML = this.myProp.css;
            },
            deep: true,
        },
    },
    mounted() {
        this.styleElement = this.document.createElement('style');
        this.styleElement.innerText = this.myProp.css;
        this.document.head.append(this.styleElement);
    },
    unmounted() {
        this.styleElement.remove();
    },
}

Though it may have some performace issues with CSS big enough.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDominik TraskowskiView Question on Stackoverflow
Solution 1 - CssDidarul Alam RahatView Answer on Stackoverflow
Solution 2 - CssMickey MullinView Answer on Stackoverflow
Solution 3 - CssNamyshView Answer on Stackoverflow
Solution 4 - CssMuthu KumaranView Answer on Stackoverflow
Solution 5 - CssNiklesh RautView Answer on Stackoverflow
Solution 6 - CssSebastianView Answer on Stackoverflow
Solution 7 - CssJohn FashView Answer on Stackoverflow
Solution 8 - CssFletcher RipponView Answer on Stackoverflow
Solution 9 - CssLaurent MeyerView Answer on Stackoverflow
Solution 10 - CssLohithView Answer on Stackoverflow
Solution 11 - CssMikhailMView Answer on Stackoverflow