Use style tags inside vuejs template and update from data model
vue-loader (and Vue template compiler Vue.compile(..)
) both will filter out any <style>
tags that are encountered in the template
.
A simple solution to get around this, is to take advantage of Vue's built-in<component>
component.
<template>
<div>
<component is="style">
.foo[data-id="{{ uniqueId }}"] {
color: {{ color }};
}
.foo[data-id="{{ uniqueId }}"] .bar {
text-align: {{ align }}
}
</component>
<div class="foo" :id="id" :data-id="uniqueId">
<div class="bar">
</div>
</div>
</div>
</template>
<script>
export default {
props: {
id: {
type: String,
default: null
}
},
computed: {
uniqueId() {
// Note: this._uid is not considered SSR safe though, so you
// may want to use some other ID/UUID generator that will
// generate the same ID server side and client side. Or just
// ensure you always provide a unique ID to the `id` prop
return this.id || this._uid;
},
color() {
return someCondition ? 'red' : '#000';
},
align() {
return someCondition ? 'left' : 'right';
}
}
}
</script>
A unique ID (or some other data-attribute) is required to "scope" the styles to just this component.
This is a nice solution as you can use v-for
loops to generate the style content if required (which can be reactive to changes in your components data/props/computed props)
<component is="style" type="text/css">
<template v-for="item in items">
[data-id="{{ uniqueId }}"] div.bar[data-div-id="item.id"]::before {
content: "{{ item.content }}";
color: {{ item.color }};
}
</template>
</component>
Here's what I think is a good workaround/solution.
It is just a custom component, so it's as reusable as it gets. All of Vue's goods like v-if
can all be used.
Another pro is that the styles generated will be there only as long as the component is!
Vue.component('v-style', {
render: function (createElement) {
return createElement('style', this.$slots.default)
}
});
// demo usage, check the template
new Vue({
el: '#app',
data: {
bgColor: 'red'
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app" class="stuff">
<v-style>
.stuff input {
background: {{bgColor}};
}
</v-style>
Remove "red" and type "yellow":
<input class="setting" type="text" v-model="bgColor">
</div>
The one drawback I see is that since the name of the tag is <v-style>
(or whatever you chose to call it) and not <style>
, the IDEs may not color it nicely. But otherwise it'll just be like a regular <style>
tag.
Standard solution: using v-bind:style
This doesn't modify style
tags, but the standard way of setting styles is using object style bindings.
Basically you'd use a :style
attribute and assign to it the CSS properties of the style in the form of an object. Demo below.
new Vue({
el: '.setting',
data: {
bgColor: 'red'
},
computed: {
inputStyles() {
return {
background: this.bgColor
}
}
}
});
<script src="https://unpkg.com/vue"></script>
<div class="setting">
Remove "red" and type "yellow":
<input class="setting" type="text" v-model="bgColor" :style="inputStyles">
</div>