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

6 Answers 6

47

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.

Sign up to request clarification or add additional context in comments.

9 Comments

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
Are you including a .scss or a .css file in the @import statements that stay present?
I found the problem, it was just a single <style> that din't have the language set: <style lang="sass">. My bad, thanks!
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?
For anyone using Bootstrap 4 you will need to import _functions.scss first before importing _variables.scss.
|
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";`
      }
    }
  }
};

2 Comments

This depends on webpack rather than vue-cli.
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.
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";'
      }
    }
  }
}

Comments

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 Comment

For Vue 3 + Vite is the same (in vite.config.ts). Thanks.
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";`
        }
      },
    },
  },
};

Comments

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.

8 Comments

Interesting idea, how would you throw <style scoped> into this setup if even possible?
@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.
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.
@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.
This is just the very best. Old fashion and straight forward, Free of duplicated and variables issues. Thumbs up @GeneParcellano
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.