Using sass variables in a VueJS component
Asked Answered
S

6

38

I got a rather simple problem with a VueJS component that needs to use a variable. The problem comes with getting sass to register variables inside a component.

I tried importing the _variables.scss file containing my variables but to no luck. At this point any guidance is very much appreciated, or if there is another way for a component to inherit styling.

MyComponent.vue

<template>
    <div class="my-color"></div>
</template>
<style lang="sass">
    .my-color {
        color: $primary-color;
    }
</style>
<script>
    export default{
        data(){
            return {}
        }
    }
</script>

Gulpfile.js

var elixir = require('laravel-elixir');
require('laravel-elixir-vueify');

elixir(function(mix) {
    mix.browserify('main.js');
    mix.sass('app.scss');
});

app.scss

@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";
@import "modules/variables";

variables.scss

$primary-color: #BA2731; //Red
Sinistrous answered 23/2, 2016 at 14:53 Comment(0)
B
46

Importing the _variables.scss in every component seems to be the only solution I've found so far (it should work, according to this issue).

<template>
    <div class="my-color"></div>
</template>
<style lang="sass">
    @import 'path/to/your/_variable.scss'; // Using this should get you the variables
    .my-color {
        color: $primary-color;
    }
</style>
<script>
    export default{
        data(){
            return {}
        }
    }
</script>

As you are only going to include variables, this shouldn't be a problem.

But as mentioned in the issue, a word of caution: You should only include abstract entities (variables, extends, mixins) into every component, no concrete CSS rules.

Bozeman answered 24/2, 2016 at 13:11 Comment(9)
Running into a problem with the @import also being present in the compiled CSS, several times, afterwards. This triggers the browser to load the file, which doesn't exist. How do we stop this? @BozemanSinistrous
Are you including a .scss or a .css file in the @import statements that stay present?Bozeman
I found the problem, it was just a single <style> that din't have the language set: <style lang="sass">. My bad, thanks!Sinistrous
Hello, when I put lang=sass in that <style> tag its fails when compile with gulp. What i need to install before to gei it working? What can I do to start using sass inside style tags?Goodson
For anyone using Bootstrap 4 you will need to import _functions.scss first before importing _variables.scss.Snot
@Goodson Maybe you are writing SCSS (lang="scss")Josphinejoss
@Bozeman does this answer still work? I tried it but after the import everything give me errors and says it's not permitted to be thereChequered
Be aware that if you import this way into 100 components your file size increases for each time you import. Better to load once globallyBulimia
@Bulimia that is true but as mentioned in the answer above it will not work if you just import it in your App.vue for example and use it trough the children elements. For me, I have to import it in every component that I use....unfortunatelyDuramen
H
31

Assuming you are using vue-cli, try this.

If you don't already have the sass loader installed:

npm install -D sass-loader node-sass

Then in vue.config.js:

const path = require('path');

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        data: `@import "@/pathto/variables.scss";`
      }
    }
  }
};

In your component:

<style lang="sass">
    .my-color {
        color: $primary-color;
    }
</style>

Source:

Edit:

As of sass-loader 8, data needs to be prependData (Thanks to @ben-y for pointing this out):

const path = require('path');

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        prependData: `@import "@/pathto/variables.scss";`
      }
    }
  }
};
Housum answered 9/4, 2019 at 0:45 Comment(2)
This depends on webpack rather than vue-cli.Josphinejoss
Depending on your webpack configs, this approach can cause the variables to be repeated in every <style> block that’s injected on the page. If you have a lot of components and variables this can significantly increase the page weight.Frambesia
M
6

I'm using the latest version (v9.0.2) of sass-loader, and prependData doesn't seem like an option now. You might want to try this configuration in vue-config.js. Notice the additionalData option is being used as there's no longer a prependData option.

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        additionalData: '@import "@/pathto/variables.scss";'
      }
    }
  }
}
Meant answered 28/7, 2020 at 12:40 Comment(0)
C
3

For Nuxt 3

Inside of nuxt.config.ts

export default defineNuxtConfig({
  css: ["@/assets/styles/main.scss"],
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@import "@/assets/styles/_variables.scss";'
        }
      }
    }
  }
})
Cabbala answered 29/9, 2022 at 21:59 Comment(1)
For Vue 3 + Vite is the same (in vite.config.ts). Thanks.Merilynmeringue
M
1

For me none of the solutions above worked (sass-loader 9.0.3) but this did:

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        sassOptions: {
          prependData: `@import "@/scss/variables.scss";`
        }
      },
    },
  },
};
Mitran answered 21/8, 2020 at 6:21 Comment(0)
H
0

For my project I used Vue CLI webpack and here's a solution that worked for me.

I manage all of my SCSS in the App.vue file. In each of my Component.vue I stopped using <style></style> and started creating a separate component.scss.


So my src folder looks like:

 /src
     /assets
     /components
         /compA
             CompA.vue
             compA.scss
         /compB
             CompB.vue
             compB.scss
    App.vue
    main.js

And my App.vue looks like

<template> ... </template>

<script> ... </script>

<style lang="less">
    //Bootstrap
    @import "../node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

    //Components
    @import "components/compA.scss";
    @import "components/compB.scss";
</style>

The advantage of this setup is getting to manage all your styles in one location, and also being able to use all your bootstrap variables and mixins.

Note:

This is just another option of using SASS variables in Vue.

I went this route since when I import the Boostrap SCSS in all of my components, the size of my app kept growing. The increase is negligible if I'm only importing the variables, but when I import the whole Boostrap SCSS the increase becomes significant. I do this so I can use the mixins and extend some existing styles.

Habilitate answered 5/7, 2017 at 22:3 Comment(8)
Interesting idea, how would you throw <style scoped> into this setup if even possible?Indochina
@Indochina This setup would avoid useing scoped actually. I personally prefer not to use it and instead use specificity. Each of my components would have their own specific class name, that would be used to encapsulate styles while still being able to use variables and mixins.Habilitate
This partly destroys the component based system Vue is based on! Why would you want to do this? Use the webpack SASS loader to import the variables into every file, as user2718281 suggested.Josphinejoss
@FabianvonEllerts I agree, but when you have a branding setup for a large company and there are a ton of variables and mixins, it didn't seem like a great idea duplicating those variables and mixins in every component. At the time, in 2017, I coudn't find a better way to do this and I did not want duplicate codes of the variables and mixins. In the present, there might be a better way. I posted it here as an alternative for others who would have to deal with mixins and large variable files.Habilitate
@GeneParcellano Maybe I'm missing something here, but variables and mixins don't output code by themselves - so it shouldn't matter how often you import them. Can't argue with the time argument though :)Josphinejoss
@FabianvonEllerts You're right. I guess the only thing this solves is not having to import variables and mixins in every component.Habilitate
This is just the very best. Old fashion and straight forward, Free of duplicated and variables issues. Thumbs up @GeneParcellanoBlackpoll
Is it possible to use globally defined SCSS variables (existing in the assets folder) in combination with <style scoped>? <style scoped> .myClass { color: $my-color-variable; } </style>Collation

© 2022 - 2024 — McMap. All rights reserved.