Pass a SASS variable to a Vue component property - css

I'm still very new to frontend development, and I'm working on a small Vue component that is basically a Vuetify card with a colored border on one side. The color is a property of the component. This works so far:
<template>
<v-card :style="borderColorStyle">
<slot></slot>
</v-card>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
export default Vue.extend({
props: {
color: {
required: false,
type: String as PropType<string>,
default: null
}
},
computed: {
borderColorStyle () {
if (this.color) {
return `border-left: 5px solid ${this.color}`
} else {
return ''
}
}
}
})
</script>
<style lang="sass" scoped>
#import '#/sass/variables.sass'
.v-card
height: 100%
border-left: 5px solid $my__darkgray
</style>
As you can see, we use SASS, and we used it to define a number of colors.
Now, how can I use these SASS definitions to set the color when using this component?
For example, if my variables.sass contains
$my_coolgreen: #288970
is there any way I can do something like this?
<StatusCard color="my_coolgreen">
Some text
</StatusCard>

Via classes
While you can't pass a Sass variable through a prop to your styles in Vue 2, you could apply a CSS class that uses the Sass variable. For example, this template uses class binding to conditionally apply .myClass based on the value of color:
<template>
<v-card :class="{ myClass: color === '$my_coolgreen' }">
</v-card>
</template>
<style lang="scss" scoped>
#import '#/sass/variables.sass'
.myClass
border-left: 5px solid $my_coolgreen
</style>
Vue 3 <style vars>
Vue 3's <style vars> (still experimental) allows using props as CSS custom properties inside the style block, as shown in the example below. However, Vuetify 2 currently does not support Vue 3.
<style lang="scss" scoped vars="{ color }">
#import '#/sass/variables.sass'
.v-card
border-left: 5px solid var(--color)
</style>

Here is what we ended up doing:
<template>
<v-card :class="['pa-2','my__status__card', color]" style="background-color: white !important">
<slot></slot>
</v-card>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue'
export default Vue.extend({
props: {
color: {
required: false,
type: String as PropType<string>,
default: 'info'
}
}
})
</script>
<style lang="sass">
.v-card
height: 100%
.my__status__card
border-style: solid !important
border-left-width: 5px !important
border-top-width: 0px !important
border-bottom-width: 0px !important
border-right-width: 0px !important
</style>
So we give the card a style that removes all borders except the left one.
The color property only works with theme colors. So this might not be a solution that makes sense for everyone, but it's what we needed.

Related

Custom global components not applying style in NuxtJs

I have built some components such as buttons and I want to use and reuse just about everywhere in my site.
I have already create plugins
Object.entries(components).forEach((([name, component]) => {
Vue.component(name, component)
}))
and registered in nuxt.config
plugins [
'#/plugins/components'
]
<style lang="scss">
.btn__container {
border-radius: '5px';
border: '1px solid red';
background-color: 'red';
}
</style>
but then when i call the component it doesnt apply the style
<v-button>button</v-button>
i am trying to inspect my custom button element and it got strikethrough i dunno why
border-radius: '5px'; is not valid CSS
Try with border-radius: 5px;!

How to change style of background color using Vue.js only

import Vue from 'vue'
import App from './App'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.config.productionTip = false
Vue.use(BootstrapVue);
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
<template>
<div id="app">
<webpage></webpage>
</div>
</template>
<script>
import webpage from "./components/webpage"
export default {
name: 'app',
components : {
webpage
}
}
</script>
<style>
</style>
i tried to change the background color of element with with vue bind styling using the command v-bind:style='{backgroundColor : color}
but its not at full height, even though i tried to remove the margin and the padding for the body element on CSS but still not working as u can see on the pic thanks
#wrapper{
width: 650px ;
height: auto;
background-color: rgb(198, 241, 200);
margin: 0 auto;
margin-top: 200px;
border-radius: 10px;
}
html,
body {
margin: 0;
padding: 0;
background-color:rgb(250, 28, 65);
}
bind your element to a style object as follows:
<div :style="myStyle" id="wrapper">
in your data object :
data(){
return{
myStyle:{
backgroundColor:"#16a085"
}
...
}
}
You could check this i made several changes in your css rules without affecting the Vue logic

VUE component ignoring CSS

I have the following VUE component:
<template>
<div>
<div class="bottom-footer">
{{msg}}
</div>
</div>
</template>
<script>
export default {
name: 'LayoutFooter',
data () {
return {
msg: 'my test'
}
},
mounted () {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.bottom-footer {
height: 200px;
background-color: #A7BFE8;
}
</scoped>
VUE is completely ignoring my scoped CSS. When page is rendered its simply not applied. There are no console errors. Ive tried removing the scoped attribute and its still ignored. Any ideas why VUE is doing this?
<style scoped>
.bottom-footer {
height: 200px;
background-color: #A7BFE8;
}
</style>
you need to close style

How to import stylesheet dynamically Polymer 2.0

I want to import my stylesheet with variable inside :
<dom-module id="colors-palette">
<template>
<style>
:host {
--dark-gray: #263238;
--light-gray: #e6ebed;
--light-blue: #00bcd4;
--autovision-blue: #174291;
--background-box-number-applications: red;
--color-box-number-applications: orange;
}
</style>
</template>
</dom-module>
I want to do it dynamically. My folder structure is :
-themes
-theme1
-style.html
-theme2
-style.html
-theme3
-style.html
I detect the theme when my-app is ready and after that I try to import my style like this in the ready function :
Polymer.importHref(this.resolveUrl('../themes/' + this.getCurrentTheme() + '/colors-palette.html'));
The file is loaded but the var in the style in my-app.html doesn't change :
app-header {
background-color: var(--dark-gray);
}
And I've got this error in the console :
Could not find style data in module named colors-palette
Any idea ? Or maybe I have to do otherwise ?
Thanks a lot
Your colors-palette.html should just contain the styles setting it globally for html.
<custom-style>
<style is="custom-style">
html {
--dark-gray: #263238;
--light-gray: #e6ebed;
--light-blue: #00bcd4;
--autovision-blue: #174291;
--background-box-number-applications: red;
--color-box-number-applications: orange;
}
</style>
</custom-style>

In vue.js component, how to use props in css?

I'm new to vue.js. Here is my problem:
In a *.vue file like this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: ?
}
<style>
How can I use the props color in background-color: (where is a ? now).
Thanks.
You actually can!
You should define the CSS variables in a Computed Property, then call the computed property as a style attribute to the element that will require the CSS variable, and finally you may use the variable within the tags at the bottom of your document.
new Vue({
el: '#app',
data: function() {
return {
baseFontSize: 1,
bgHoverColor: "#00cc00",
hoverContent: "Hovering!"
}
},
computed: {
cssProps() {
return {
'--hover-font-size': (this.baseFontSize * 2) + "em",
'--bg-hover-color': this.bgHoverColor,
'--hover-content': JSON.stringify(this.hoverContent)
}
}
}
})
div {
margin: 1em;
}
div.test:hover {
background-color: var(--bg-hover-color);
font-size: var(--hover-font-size);
}
div.test:hover::after {
margin-left: 1em;
content: var(--hover-content);
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app" :style="cssProps">
<div>Hover text: <input type="text" v-model="hoverContent"></div>
<div>Hover color: <input type="color" v-model="bgHoverColor"></div>
<div class="test">Hover over me</div>
</div>
Or have a look here: https://codepen.io/richardtallent/pen/yvpERW/
And here: https://github.com/vuejs/vue/issues/7346
You don't. You use a computed property and there you use the prop to return the style of the div, like this:
<template>
<div id="a" :style="style" #mouseover="mouseOver()">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color'],
computed: {
style () {
return 'background-color: ' + this.hovering ? this.color: 'red';
}
},
data () {
return {
hovering: false
}
},
methods: {
mouseOver () {
this.hovering = !this.hovering
}
}
}
</script>
<style scoped>
<style>
As we are in 2020 now, I suggest using this trick with a css function called var
<template>
<div id="a" :style="cssVars"></div>
</template>
<script>
export default {
props: ['color'],
computed: {
cssVars () {
return{
/* variables you want to pass to css */
'--color': this.color,
}
}
}
<script>
<style scoped>
#a{
background-color: var(--color);
}
</style>
This method is very useful because it allows you to update the passed values through css later on (for example when you apply hover event).
credit
I know we're talking vue 2 here, but in case anyone from vue 3 lands in this question (like I did), vue 3 introduced a much cleaner way to do this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: v-bind(color);
}
<style>
What Vue actually does behind the scenes is the same "introducing css variables through component's style process", but it sure looks much better on the eyes now.
Documentation source: https://v3.vuejs.org/api/sfc-style.html#state-driven-dynamic-css
Why not just use :style prop in this way:
<template>
<div :style="{ backgroundColor: color }">
</template>
<script>
export default {
props: {
color: {
type: String,
default: ''
}
}
}
</script>
Make sure you define css properties in camelCase style.
If you need css that can't be applied by a style attribute like pseudo classes or media queries, what I do is the following:
Create a globally available style component when initializing Vue (you need it as otherwise you run into linting issues). It creates a style tag that simply renders the content in the slot:
I would only use this if you really need both dynamic values in your css and css features that can't be applied to a style attribute.
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
Vue.component('v-style', {
render: function(createElement) {
return createElement('style', this.$slots.default)
}
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Then use it at the top of your template like this and you get the full JavaScript scope of your component and the full css syntax combined:
<template>
<v-style>
#media screen and (max-width: 820px) {
.gwi-text-media-{{ this.id }} {
background-image: url({{ mobileThumb }});
}
}
</v-style>
</template>
It seems a bit hacky to me, but it does it's job and I would rather go like this in some cases than having to add additional JS for mouse-over or resize events that have a big potential to slow down your application performance.
Vue 3 added new way of binding styles, so now you can easily bind your props to css properties.
Read source:
https://learnvue.co/2021/05/how-to-use-vue-css-variables-reactive-styles-rfc/
<template>
<div>
<div class="text">hello</div>
</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
You could utilise the CSS var(--foo-bar) function. It is also useful if you are trying to pass an asset that has its own dynamic path, like Shopify does.
This method also works for styling the :before and :after elements as they refer back to the style applied on the owner element.
Using the original post example for passing a colour:
<template>
<div
id="a"
:style="{ '--colour': color }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: var(--colour);
}
</style>
Using the original post example for passing an URL:
<template>
<div
id="a"
:style="{ '--image-url': 'url(' + image + ')' }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['image']
}
</script>
<style scoped>
#a {
background-url: var(--image-url);
}
</style>
Source

Resources