Vue - getting data attribute value in css - css

Is there any option to get data attribute value in Vue css?
<template>
<p data-background="purple"> TEST </p>
</template>
<style lang="scss">
p {
background: attr(data-background); //error
&:after {
background: attr(data-background); //error
}
}
</style>

You could use CSS variables for this case.
new Vue({
el: '#app',
data: {
elStyle: {
'--background': 'lightblue',
}
}
});
p:after {
content: 'A pseudo element';
background: var(--background, red); // Red is the fallback value
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p :style="elStyle"></p>
</div>

Related

Vue adding dynamic class doesn't change current class

I have wrapper div with padding and I am dynamically adding items inside of it.
I don't want any padding on wrapper div when there is no item in it.
I have created computed method isEmpty to check if there are items or not and used it to add optional class :class={ className: isEmpty } but it doesn't work.
Here is the fiddle link: https://jsfiddle.net/2u9rtdmh/3/
You should wrap an expression for :class into ":
:class="{ className: isEmpty }"
You should read the console errors when trying to diagnose problems, i.e. your jsfiddle doesn't even have an #app element.
The correct syntax for your scenario would be :class="{ 'padding0' : isEmpty }"
Binding HTML Classes
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: "#app",
data: {
},
computed: {
isEmpty() {
return true;
}
}
})
body {
background-color: black;
}
.my-wrapper {
padding: 32px;
background-color: white;
}
.padding0 {
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div :class="{ 'padding0' : isEmpty }" class="my-wrapper">
<div>
<div>
</div>
</div>
</div>
</div>

Why CSS styles can't be applied to elements created by Buefy?

I'm trying to change the background-color of a table row that was generated by Buefy.
I don't understand why I'm unable to change the color of the table row, but I can change its children color.
I tried both ways, setting the whole class name or just the class name of the element that I want:
.table.is-hoverable tbody tr.detail:not(.is-selected):hover {
background-color: rgb(218, 11, 11) !important;
}
.detail {
background-color: rgb(218, 11, 11) !important;
}
I can, for example change the color of an inner element:
.media {
background-color: yellow !important;
}
Full code
<template>
<section class="hero">
<div class="hero-body">
<div class="container">
<b-table
:data="downloads"
ref="table"
:loading="isLoading"
hoverable
detailed
detail-key="version"
selectable
#select="toggle"
>
<template slot-scope="props">
<b-table-column
class="is-unselectable"
cell-class="has-pointer-cursor"
field="version"
label="Version"
width="70"
>
<span class="tag is-info">{{ props.row.version }}</span>
</b-table-column>
<b-table-column
class="is-unselectable"
cell-class="has-pointer-cursor"
field="download_count"
label="Download Count"
sortable
numeric
>{{ props.row.download_count.toLocaleString() }}</b-table-column>
<b-table-column
class="is-unselectable"
cell-class="has-pointer-cursor"
field="release_date"
label="Release Date"
sortable
centered
>{{props.row.release_date ? new Date(props.row.release_date).toLocaleDateString() : "unknown"}}</b-table-column>
</template>
<template slot="empty">
<section v-if="!isLoading" class="section">
<div class="content has-text-grey has-text-centered">
<p>Looks like it was not possible to load the data.</p>
</div>
</section>
</template>
<template slot="detail" slot-scope="props">
<article class="media">
<div class="media-content">Some text.
<hr>Some other text.
</div>
</article>
</template>
<template slot="footer">
<div v-if="!isLoading" class="has-text-right">This is a footer.</div>
</template>
</b-table>
</div>
</div>
</section>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
downloads: [],
isLoading: true
};
},
mounted() {
this.downloads = [
{ version: "1.5", download_count: 500, release_date: new Date() },
{ version: "1.4", download_count: 400, release_date: new Date() },
{ version: "1.3", download_count: 300, release_date: new Date() },
{ version: "1.2", download_count: 200, release_date: new Date() },
{ version: "1.1", download_count: 100, release_date: new Date() }
];
this.isLoading = false;
},
methods: {
toggle(row) {
this.$refs.table.toggleDetails(row);
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
//This is how I expect it should work.
.table.is-hoverable tbody tr.detail:not(.is-selected):hover {
background-color: rgb(218, 11, 11) !important;
}
//Applying the property to the
.detail {
background-color: rgb(218, 11, 11) !important;
}
.media {
background-color: yellow !important;
}
</style>
Reproduction link:
https://codesandbox.io/s/misty-sea-bmyvc?file=/src/components/HelloWorld.vue
Your CSS is scoped. In the end those classes are assorted with a [data-xxx] selector so they are applied only on this component.
.detail[data-xxx] won't override the lib's CSS, you need just .detail
So put this CSS code into a separated simple <style lang="scss"> and let your component's own CSS in <style lang="scss" scoped>

Assign a dynamic Vuejs value to css

I have the following jsfiddle:
https://jsfiddle.net/6cu295sn/1/
new Vue({
el: '#cct',
lang: {
myText: "my text is",
}
});
.myCSS::after{
content: {{lang.myText}}; //this does not output anything
}
I am trying to assign the Vuejs dynamic value to the CSS (content), please can anyone advise how I can achieve this?
You can bind a css variable, to apply it as content of your pseudo class, as below:
new Vue({
el: '#cct',
data () {
return {
lang: "my text is"
}
}
})
.myCSS {
margin: 1rem 0;
border: 1px solid black;
}
.myCSS::after {
content: var(--myText);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<div id="cct">
<input v-model="lang">
<div class="myCSS" :style="`--myText: '${lang}'`"></div>
</div>

Knockout js CSS binding

I am using the Knockout js in my project,I need to add multiple css class name to particular tag.below is my code i have three different class how i can add it in knockout css binding kindly suggest.
<img data-bind="attr: { src:ProfileImageSrcName }" class="tabUser profile-Image tabpic" />
you can ise css binding like below.
var vm = {
profileImageSrcName: ko.observable('http://cumbriaskills.wdfiles.com/local--files/files:images/metro_128_chrome.png'),
isProfilePic: ko.observable(true),
isTab: ko.observable(true),
toggleProfile: function() { vm.isProfilePic(!vm.isProfilePic()); },
toggleTab: function() { vm.isTab(!vm.isTab()); }
};
ko.applyBindings(vm);
.tabUser { width: 100px; height: 100px; object-fit: contain; }
.profile-image { border-radius: 100% }
.tabPic { box-shadow: 0 2px 6px rgba(0,0,0,0.4) }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<img data-bind="attr: { src: profileImageSrcName },
css: {
'profile-image': isProfilePic, /* single class */
'tabUser tabPic': isTab /* multiple classes */
}" />
<br><br>
<button data-bind="click: toggleProfile">Toggle "profile-image" Class</button><br>
<button data-bind="click: toggleTab">Toggle "tabUser" and "tabPic" Classes</button>
Use css binding to assign multiple class name.
http://knockoutjs.com/documentation/css-binding.html
var masterVM = (function () {
var self = this;
self.classNames = ko.pureComputed(function(){
return "className1 className2 className3";
}, self);
})();
ko.applyBindings(masterVM);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="existingClass" data-bind="css: classNames">
Inspect this element to see list of the 4 class names.
</div>

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