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
Nicklas Kevin Frank
  • 6,079
  • 4
  • 38
  • 63

6 Answers6

44

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.

nils
  • 25,734
  • 5
  • 70
  • 79
  • 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? @nils – Nicklas Kevin Frank Feb 25 '16 at 13:20
  • Are you including a `.scss` or a `.css` file in the `@import` statements that stay present? – nils Feb 25 '16 at 13:26
  • I found the problem, it was just a single ` – Nicklas Kevin Frank Feb 25 '16 at 13:32
  • Hello, when I put lang=sass in that – Zalo Aug 31 '16 at 10:13
  • For anyone using Bootstrap 4 you will need to import `_functions.scss` first before importing `_variables.scss`. – Chris Apr 04 '18 at 21:04
  • @Zalo Maybe you are writing SCSS (`lang="scss"`) – Fabian von Ellerts Sep 19 '19 at 14:15
  • @nils does this answer still work? I tried it but after the import everything give me errors and says it's not permitted to be there – Nancy Apr 04 '20 at 19:20
  • Be aware that if you import this way into 100 components your file size increases for each time you import. Better to load once globally – BobB May 12 '20 at 18:02
  • @BobB 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....unfortunately – JohnRambo Aug 13 '20 at 08:55
30

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";`
      }
    }
  }
};
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
logee
  • 5,017
  • 1
  • 26
  • 34
  • 3
    This depends on webpack rather than vue-cli. – Fabian von Ellerts Sep 19 '19 at 14:17
  • Depending on your webpack configs, this approach can cause the variables to be repeated in every – emersonthis Sep 21 '22 at 12:16
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";'
      }
    }
  }
}
Oli
  • 314
  • 3
  • 13
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";'
        }
      }
    }
  }
})
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";`
        }
      },
    },
  },
};
Wolle
  • 421
  • 5
  • 8
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.

Gene Parcellano
  • 5,799
  • 5
  • 36
  • 43
  • 1
    Interesting idea, how would you throw ` – Fractalf Nov 28 '17 at 09:48
  • @Fractalf 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. – Gene Parcellano Nov 28 '17 at 15:21
  • 1
    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. – Fabian von Ellerts Sep 19 '19 at 14:29
  • @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. – Gene Parcellano Sep 19 '19 at 14:53
  • @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 :) – Fabian von Ellerts Sep 19 '19 at 16:57
  • @FabianvonEllerts You're right. I guess the only thing this solves is not having to import variables and mixins in every component. – Gene Parcellano Sep 19 '19 at 17:01
  • 1
    This is just the very best. Old fashion and straight forward, Free of duplicated and variables issues. Thumbs up @GeneParcellano – Vixson Apr 22 '20 at 01:10
  • Is it possible to use globally defined SCSS variables (existing in the assets folder) in combination with – Luckytechy Jul 08 '22 at 09:24