Ben Casalino
Ben Casalino

Reputation: 2383

CSS variables use in Vue

Is it possible to use pure CSS variables with Vue without having to link any stylesheets or use SASS/PostCSS? Unsure why I'm unable to get this to work in its most basic form.

<template>
   <div id="test">
        TEST
    </div>
</template> 
<style scoped> 
   :root {
   --var-txt-color: #c1d32f;
   }

 #test {
 color: var(--var-txt-color);
  }
</style> 

Upvotes: 32

Views: 57053

Answers (6)

Tarek Adam
Tarek Adam

Reputation: 3525

Late answer - Here is a working example with css vars derived from standard vue structures.

<template>
  <div>
  <component :is="'style'">
    :root {
    --color: {{ color }};
    --text-decoration: {{ textDecoration }};
    --font-size: {{ fontSize }};
    }
  </component>
    <p>example</p>
  </div>
</template>

<script>

export default {

  props:{
    color: {
      type: String,
      default: '#990000'
    }
  },

  data: function () {
    return {
      textDecoration: 'underline'
    }
  },

  computed: {
    fontSize: function (){
      return Math.round(Math.random() * (5 - 1) + 1) + 'em';
    }
  }
}
</script>

<style>
p{
  color: var(--color);
  text-decoration: var(--text-decoration);
  font-size: var(--font-size);
}
</style>

Starting from the top...

  • Vue must have 1 root element, so I needed a div tag in order to include a sample p tag. However, you can just use the component-is-style tag and get rid of the div and p tags. Note the need for extra quotations "'style'".
  • The normal vue style tag can be scoped or not - as needed.

Upvotes: 6

m4heshd
m4heshd

Reputation: 970

Well, now you can use CSS variable injection.

<template>
  <div>
    <div class="text">hello</div>
  </div>
</template>

<script>
  export default {
    data() {
        return {
            color: 'red',
            font: {
                weight: '800'
            }
        }
    }
  }
</script>

<style>
  .text {
    color: v-bind(color);
    font-weight: v-bind('font.weight');
  }
</style>

Those styles are also both reactive and scoped. There won't be any unintended inheritance issues. Vue manages the CSS variables for you.

You can take a look at the RFC here.

Upvotes: 6

Manoj Shrestha
Manoj Shrestha

Reputation: 4684

One workaround is to define them under a non-scoped style element like the following. However one thing to note here is, these variables will be exposed to other Vue components as well.

<style>
  :root {
     --var-txt-color: #c1d32f;
  }
</style>

<style scoped>
  #test {
     color: var(--var-txt-color);
  }
</style> 

Upvotes: 6

flyingL123
flyingL123

Reputation: 8076

Why not just use this?

<style scoped>
  * {
    --var-txt-color: #c1d32f;
  }
</style>

The generated CSS is:

*[data-v-d235d782] {
  --var-txt-color: #c1d32f;
}

This has been working for me.

I just discovered that it looks like this also works, using the "deep selector"

>>>  {
  --var-txt-color: #c1d32f;
}

Generated CSS is:

[data-v-d235d782] {
  --var-txt-color: #c1d32f;
}

I think I like this method more.

Upvotes: 13

ThePianist
ThePianist

Reputation: 719

I know you highlighted "without having to link any stylesheet", but I run into the same issue and there is a simple option - use just one external css file and include it in your App.vue, then you can access the variables anywhere else, in scoped styles as well.

variables.css

:root {
  --font-family: "Roboto", "Helvetica", "Arial", sans-serif;
  --primary-color: #333a4b;
}

App.vue

<style>
  @import './assets/styles/variables.css';
</style>

LandingView.vue

<style scoped>
  #landing-view {
    font-family: var(--font-family);
    font-weight: 300;
    line-height: 1.5em;
    color: var(--primary-color);
  }
</style>

Upvotes: 40

aBiscuit
aBiscuit

Reputation: 4732

This won't work as expected because of scoped attribute for stylesheet. Example above compiles into:

[data-v-4cc5a608]:root {
  --var-txt-color: #f00;
}

And, as you understand, it will not target actual :root element.

It can be solved by:

  • Not using scoped attribute for this stylesheet. Notice that it may cause styles conflict with other variables declarations for :root element.

  • Using current component's wrapping element as root. If we declare variables this way:

    .test {
      --var-txt-color: #c1d32f;
      color: var(--var-txt-color);
    }
    
    .test-child-node {
      background-color: var(--var-txt-color);
    }
    

Then it will can reuse variables for other elements of the same component. But still, it won't be possible to use declared variables inside child components without removing scoped, if it is the case.

Upvotes: 33

Related Questions