Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load a global settings.scss file in every vue component? #328

Closed
westwick opened this issue Aug 26, 2016 · 152 comments

Comments

@westwick
Copy link
Contributor

commented Aug 26, 2016

I find myself repeating this same pattern in every component:

<style lang="scss">
  @import "../styles/settings.scss";

  .someclass { color: $some-variable; }
</style>

My settings.scss only contains variables. An additional pain point is that I have my components nested in several folders for better organization, so I always have to be careful to specify the path to my settings.scss properly. It'd be great if there was a way to globally include a settings.scss or similar file.

@lessYFF

This comment has been minimized.

Copy link

commented Sep 9, 2016

I have the same question,but also have no answer.

@ericcirone

This comment has been minimized.

Copy link

commented Sep 20, 2016

I basically have the same question as well.

@sqal

This comment has been minimized.

Copy link
Contributor

commented Sep 21, 2016

@jbruni

This comment has been minimized.

Copy link
Contributor

commented Sep 23, 2016

I do not know the answer to the main question (global scss load).

But regarding the additional pain point (adjust relative path), maybe you can mitigate it by configuring a Webpack alias.

You would use @import "styles/settings.scss" in all your files, having a webpack config like this:

{
  resolve: {
    alias: {
      styles: 'path/to/your/styles'
    }
  }
}

Docs:
https://webpack.github.io/docs/resolving.html
https://webpack.github.io/docs/configuration.html#resolve-alias

@ericcirone

This comment has been minimized.

Copy link

commented Sep 23, 2016

Neither of these solutions solves the fact that styles.scss will be repeated on your page for however many files you include it in. That just seems not thought out and very wasteful.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Sep 23, 2016

@ericcirone We have to differenciate:

Sharing Variables & Settings

The OP asked about importing a .scss for shared variables & settings.

Such a file usually does not contain any CSS, but only SCSS $variables, mixins etc. (as stated by the OP himself) - so there would be no repeated CSS in your final, compiled files.

Granted, it's tedious to add this @import statement in every component, but it does not change anything about filesize or performance.

Sharing styles

You wrote about importing styles.scss in multiple files - so , judging from the filename, you seem to ask how to deal with shared styles.

For this scenario, you simply do an import of the shared style file in your main.js file once. As CSS has no local scope, these styles will be available anywhere in your app so you don't have to import them anywhere else.

@jbruni The alias is a good solution to relative paths, yep! 👍

But you should use an absolute path:

{
  resolve: {
    alias: {
      styles: path.resolve(__dirname, '../src/path/to/your/styles') // relative to the location of the webpack config file!
    }
  }
}
@ericcirone

This comment has been minimized.

Copy link

commented Sep 23, 2016

@LinusBorg i got ya! I'm new to Sass and Vue. My problem was that i'm building a project with Foundation and tried importing in the Foundation main app.scss in all my <style> blocks so I could use the Foundation variables and was getting repeating code everywhere.

@gregorskii

This comment has been minimized.

Copy link

commented Sep 23, 2016

@ericcirone under the current setup you have to go into the foundation scss folder and find the partials from the src folder that contain the variables and the mixins, then import those in every file. You likely do not need to import the entire main.scss file in every partial if that's what you are doing.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Sep 26, 2016

Clsoing as this issue seems to be solved.

@uptownhr

This comment has been minimized.

Copy link

commented Dec 8, 2016

I'd ask to leave this open as the real issue is being able to use scss variables, mixins in component definitions. Although css automatically cascades down, if you wanted to use a globally defined sass variable inside your component, you will not be able to use the $variable synthaxx.

//global.scss
$white = '#fff'

//component.vue
<style>
.background {
  color: $white;
}
</style>

this will fail and a solution to this would turn my world around.

@westwick

This comment has been minimized.

Copy link
Contributor Author

commented Dec 8, 2016

I also think this should remain open. I'd love to be able to use global scss variables throughout components without importing every time.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

Well, this is something that vue-loader is not suited to solve - it would have to be solved in sass-loader etc., because each pre processor might have a different syntax/ way of adding such a file.

Stylus-loader offers such a functionality, by the way.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 8, 2016

@uptownhr well you can simply import your variables file in each component. It's a one-line copy&paste for each component, but it works.

@jpt

This comment has been minimized.

Copy link

commented Dec 11, 2016

@LinusBorg wrote

Stylus-loader offers such a functionality, by the way.

Can you point to an example of this with Stylus?

+1 to everyone asking for this issue to remain open, even if means waiting until a pull request eventually finds its way to sass-loader. This functionality should be a Vue product requirement, frankly.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 11, 2016

Can you point to an example of this with Stylus?

This is not very well documented, I only read about it in a docs example for using a plugin:

https://github.com/shama/stylus-loader#using-nib-with-stylus

The import option will load the file "globally" as far as I have tested it.

+1 to everyone asking for this issue to remain open, even if means waiting until a pull request eventually finds its way to sass-loader.

We will not keep issues open for 3rd-party libs that we have no influence on, and likely won't require a change in vue-loader if they and in the 3rd-party lib (such changes would likely be implemented in loader configs, like the above import for stylus-loader, which vue-loader doesn't "care" about).

You will be better of asking for this in the respective loader's repos.

@kidBrazil

This comment has been minimized.

Copy link

commented Dec 21, 2016

I too have the same problem. I really want to use a full Vue.JS Webpack stack on my next project. However.. not being able to import SASS variables is almost a deal breaker here. I guess for now I will compile global styles separately and use minimal styling in the components themselves.

There has to be a solution to importing variables and mixins no? Or making them globally available on compile?

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 22, 2016

I'm not sure if you missed it, so repeating myself again: you can of course simply @import your variables.

This threads was about doing that automatically, which is not possible and frankly, (repeating myself again, see previous reply) cannot be the job of vue-loader to provide that for all the available pre-processors.

@westwick

This comment has been minimized.

Copy link
Contributor Author

commented Dec 22, 2016

I think you guys should seriously reconsider your position on this. At this point, SASS is the preprocessor of choice for at least 50% of devs (or a lot more, depending on which poll you're looking at). I really like keeping my components' css local to that component but it's a PITA when developing to have to import my settings.scss every time I start a new component, and having to take care to make the path right, and then it also makes the code slightly more verbose. Then if you ever move your component's path you have to update that import statement, etc. etc. Without this ability, I've resorted to the more traditional method of having all my scss files totally separate from the components, which defeats a good chunk of the the purpose of using vue-loader / .vue components IMO. Although to be totally fair I have not looked into the other options of getting this to work (such as the stylus one you linked). Either way, thanks for your work on this project.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 22, 2016

You easily reduce the pain about the paths with a webpack alias, reducing the statement to e.g. @import "vars", working everywhere.

Considering the number of import statements we have in the JavaScript of most components, that should be manageable.

Adding this automatically with vue-loader would be a hack. For starters, `lang="sass" can mean SCSS or SASS syntax, depending on the sass-loader config. So which do we choose when we prep end the @import string to the content of the script tag? We would have to interpret the webpqck settings somehow, etc.

@westwick

This comment has been minimized.

Copy link
Contributor Author

commented Dec 22, 2016

That's a fair point and I think a webpack alias can be a good "workaround". It's definitely more explicit to always use an import statement, which you could argue is better.

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 22, 2016

Great :)

@uptownhr

This comment has been minimized.

Copy link

commented Dec 23, 2016

quick question, when you @import 'vars' in all your components, will this bloat your build? Meaning, will webpack be able to compile this into a commons?

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Dec 23, 2016

Concerning filesize, this has no influence if the imported file only contains SCSS variables and no actual CSS markup.

Concerning memory / compile speed, this should be so small as to be neglegable - I haven't seen any issues with it in dev.

There are other parts of the build process that should be optimized if you experience longer (Re)build times in dev. (vendor chunks, DLL splitting ..)

@delucis

This comment has been minimized.

Copy link

commented Jan 1, 2017

Is there anything more needed to get Webpack aliases working in .vue components?

I set a resolve.alias for my style directory as suggested above, and can import/require from a Javascript file, but if I do @import "styles/_vars.scss" in a .vue component, I get a “File to import not found or unreadable” error.

File structure:

webpack.config.js
src/
├ components/
│ └ my-component.vue
└ style/
  └ _vars.scss
// webpack.config.js
{
  resolve: {
    alias: {
      'styles': path.resolve(__dirname, './src/style/')
    }
  }
}
<!-- my-component.vue -->
<style lang="sass">
  @import "styles/_vars.scss";
</style>

I’ve tried all kinds of variations on the import directive with no success, and a direct alias to the variables file also produces an error.

It does work using an absolute path (no Webpack alias), but I’d like to avoid the fragility that introduces:

@import "./../style/vars";

Any help appreciated!

@LinusBorg LinusBorg reopened this Jan 1, 2017

@LinusBorg

This comment has been minimized.

Copy link
Member

commented Jan 1, 2017

@import "~styles/_vars.scss";

@LinusBorg LinusBorg closed this Jan 1, 2017

@rcosta-gcare

This comment has been minimized.

Copy link

commented Nov 1, 2018

The documentation here is very very helpful and easy to understand.
https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders

@Zver64

This comment has been minimized.

Copy link

commented Nov 6, 2018

I was able to solve these problems:

  • One global SCSS import which itself imports other SCSS files
  • Variables and mixins available in all components
  • Overrides included once, after all components
  • Ability to include global one time use code-generating CSS

by doing this:
1)Importing variables, mixins and other sass things that will be removed after compiling. Import in vue.config.js:

module.exports = {
  css: {
    loaderOptions: {
      // pass options to sass-loader
      sass: {
        // @/ is an alias to src/
        // so this assumes you have a file named `src/variables.scss`
        data: `@import "@/styles/sassHelpers.scss";`
      }
    }
  }
}
  1. Adding global styles only once by importing them into the root component. In App.vue style section:
<style lang="scss">
  @import "./styles/style";
...

The problem with Automatic imports that vue plugin offers us is that it is only for sass variables, colors and other sass helpers. It is not for styles.
Here what the Official documentation says:

If you want to automatically import files (for colors, variables, mixins... ), you can use the style-resources-loader.

@jhlim82

This comment has been minimized.

Copy link

commented Nov 30, 2018

It's not the solution and might be bad way to avoid importing global stylesheet in every component.
But I would like to share my way.

I created vue.js (using stylus) project via vue-cli 3.x.

I'm using reset-css file, global-css file and mixin variable file in my project.

The important thing, to avoid importing global stylesheet in every component, is using none-pre-compiled stylesheet file.

In my variables.styl

// * import node_modules stylesheet
@import '~reset-css/reset.css';

// * import global.css
@import './global.css'

// * stylus mixins
// 1. f_ for font
f_fam = 'Avenir', Helvetica, Arial, sans-serif
f_def = 14px
f_lg = 16px
f_sm = 12px
// 2. b_ for border
b_btm_1 = 1px #ebebeb solid
// 3. bg_ for background
bg_url = url('~/img/common/bg_sprites.png')

In my global.css

/* my global.css */
figure, figcaption {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
  overflow: hidden;
}

In my vue.config.js

const path = require('path')

module.exports = {
  chainWebpack: config => {
    const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
    types.forEach(type => addStyleResource(config.module.rule('stylus').oneOf(type)))
  }
}

function addStyleResource (rule) {
  rule.use('style-resource')
    .loader('style-resources-loader')
    .options({
      patterns: [
        path.resolve(__dirname, './src/assets/style/variables.styl'),
      ]
    })
}

then, you can import your global stylesheet just once.

2018-11-30 2 36 05

@SylannBin

This comment has been minimized.

Copy link

commented Dec 13, 2018

I would like to share that I find this part of the doc insufficient.

// you can also read from a file, e.g. variables.scss
data: $color: red;

It would be the very minimum to add a line for the typical path to a file containing globals. By typical, I mean "with the alias resolution" or with an import statement.

The better way would be to explain what is possible because I still don't get at all what is going on here.
If this is something from webpack, might as well add a link?

@Jack-Barry

This comment has been minimized.

Copy link

commented Dec 15, 2018

Looks like @kinoli and @Zver64 have the right idea. There's even an article here that covers how to do it for both vue-cli and non-vue-cli projects. Took all of 3 minutes to get this implemented in my project.

The only gotchas I ran into were the age-old syntax slip-ups. 🤦 (Don't forget that semicolon following your @import statements, kids!)

@kayoderock I have a link to that in this comment already.

@kayoderock

This comment has been minimized.

Copy link

commented Jan 9, 2019

I feel the best solution I have seen is this:
https://vueschool.io/articles/vuejs-tutorials/globally-load-sass-into-your-vue-js-applications/

@mittalyashu

This comment has been minimized.

Copy link

commented Jan 30, 2019

@kayoderock I tried that solution it didn't work for me

I am getting this error

@ ./node_modules/vue-style-loader??ref--9-oneOf-1-0!./node_modules/css-loader??ref--9-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--9-oneOf-1-2!./node_modules/sass-loader/lib/loader.js??ref--9-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/pages/index.vue?vue&type=style&index=0&lang=sass& 4:14-453 14:3-18:5 15:22-461
@kayoderock

This comment has been minimized.

Copy link

commented Jan 30, 2019

@kayoderock I tried that solution it didn't work for me

I am getting this error

@ ./node_modules/vue-style-loader??ref--9-oneOf-1-0!./node_modules/css-loader??ref--9-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--9-oneOf-1-2!./node_modules/sass-loader/lib/loader.js??ref--9-oneOf-1-3!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/pages/index.vue?vue&type=style&index=0&lang=sass& 4:14-453 14:3-18:5 15:22-461

Are you using Vue CLI 3

@mittalyashu

This comment has been minimized.

Copy link

commented Jan 30, 2019

Yes @kayoderock, I am using Vue CLI 3

@kayoderock

This comment has been minimized.

Copy link

commented Jan 30, 2019

@mittalyashu Please, Do you have your vue.config.js file? and do you have the sass loader module?

@mittalyashu

This comment has been minimized.

Copy link

commented Jan 30, 2019

Yes. I have both vue.config.js file and sass-loader and node-sass loader module

Here's the vue.config.js file

module.exports = {
	css: {
		loaderOptions: {
			sass: {
				data: `
                                         @import "@/assets/css/helpers/_helpers.sass";
                                `
			}
		}
	}
}
@kayoderock

This comment has been minimized.

Copy link

commented Jan 30, 2019

@mittalyashu Can I see the way you did your style in the index.vue file, Are you writing SCSS or SASS ?

@kidBrazil

This comment has been minimized.

Copy link

commented Jan 30, 2019

Here is my solution to this issue. Has worked perfectly for me ever since. Uses the newest MiniCssExtractPlugin compatible with Webpack 4.

  • No CSS Duplication
  • No weird errors
  • PostCSS works flawlessly

Webpack Common

// Webpack 4
 ...
 module: {
    rules: [
      // CSS & SCSS Processing
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
          {
            loader: 'sass-resources-loader',
            options: {
              // Load common SCSS [ Vars & Mixins ]
              resources: './src/assets/styles/shared.scss',
            },
          }
        ],
      },
  ...

App.vue

<template>
  <main id="app">
    <!-- Skip Navigatio Accessbility -->
    <button href="#mainContent"
      title="Skip to main content"
      aria-label="Skip to main content"
      v-on:click.stop.prevent="skipNav"
      class="mdev-skipnav" tabindex="0">
      Skip To Main Content
    </button>

    <main-navigation></main-navigation>
    <transition name="fade">
      <router-view></router-view>
    </transition>
  </main>
</template>




<script>

//Local Component registration
import MainNavigation from './components/shared/navigation.vue';

export default{

  components: {
    'main-navigation' : MainNavigation
  },

  methods: {
    skipNav() {
      var anchor = $("#mainContent").offset().top;
      $('html,body').scrollTop(anchor);
    }
  }
};
</script>



<style lang="scss">
// Loads global stylesheets (Excludes mixins and Vars loaded via sass-resources-loader)
@import './assets/styles/global-main.scss';

// Can add styles here referencing mixins or variables and it works!

</style>
@mittalyashu

This comment has been minimized.

Copy link

commented Jan 30, 2019

@kayoderock A component file, looks something like this with SASS.

<template>
...
</template>

<script>
...
</script>

<style lang="sass">
 // Styles over here...
</style>
@kayoderock

This comment has been minimized.

Copy link

commented Jan 30, 2019

@mittalyashu I suspect you are writing SCSS in your style , while you stated the lang="sass", change it to lang="scss".

Let me know if this is the case else, I check out your error log again.

@lucho20pt

This comment has been minimized.

Copy link

commented Feb 18, 2019

well i'm new to vue but i fix it very simple like the example below ;)

file structure

- ./src/App.vue
- ./src/views/About.vue
- ./src/scss/global.scss
- ./src/scss/variables.scss
- ./vue.config.js

App.vue

<style lang="scss">
@import "./scss/global.scss";
}

./scss/global.scss

@import "./scss/variables.scss";
@import "./scss/sassfile.scss";

./scss/variables.scss

$orange : orange;
$red : red;

./scss/_sassfile.scss
now all the links in my components or views have color orange

a{
    color: $orange;
}

for each one component or view you can override it
and make it own style only for each one using scoped
and it will assume that color RED only for that component or view

./views/About.vue

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
a {
  color: RED;
}
</style>

This way calling the scss var present in scss/variables.scss in the style of the component
it still not work so lets fix it this way

creating a vue.config.js in root project with this code

module.exports = {
  css: {
    loaderOptions: {
      // pass options to sass-loader
      sass: {
        // @/ is an alias to src/
        // so this assumes you have a file named `src/scss/variables.scss`
        data: `@import "@/scss/variables.scss";`
      }
    }
  }
}

Now you can use the sass vars in the style tag
./views/About.vue

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
a {
  color: $red;
}
</style>

i will leave here a copy of my package.json

{
"name": "vue-projectname",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"baseline": "^0.3.0",
"vue": "^2.5.22",
"vue-router": "^3.0.1",
"vuetify": "^1.5.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.4.0",
"@vue/cli-plugin-eslint": "^3.4.0",
"@vue/cli-service": "^3.4.0",
"@vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.9.0",
"sass-loader": "^7.1.0",
"vue-template-compiler": "^2.5.21"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"@vue/standard"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

@golgote

This comment has been minimized.

Copy link

commented Feb 24, 2019

Don't want people to be able to use your components ? Just add sass in your .vue files...
Ever heard of Separation of Concerns ?

@kayoderock

This comment has been minimized.

Copy link

commented Feb 24, 2019

@golgote you are right. What I put in those files are general styles like application primary color etc

@nellysattari

This comment has been minimized.

Copy link

commented Mar 4, 2019

That also combined some solutions in one post:
https://css-tricks.com/how-to-import-a-sass-file-into-every-vue-component-in-an-app/

@ByungWookYe

This comment has been minimized.

Copy link

commented Mar 7, 2019

If you create your project with
vue init webpack prjName command.

you might solve this issues by change generateLoaders function on /build/utils.js like this
sass: generateLoaders('sass', { indentedSyntax: true, data: '@import "@/sass/vue-globals.scss";' }), scss: generateLoaders('sass', { data: '@import "@/sass/vue-globals.scss";'}),

/sass/vue-globals.scss

@import "@/sass/base/base_mixin.scss";
@import "@/sass/base/palette.scss";

I'm quite new for vueJS or webpack stuffs, I'm not sure it's right solution.
I tried alot of solutions above, but none them work for me.
except this one.(My own way)

I hope this helps someone :)

@kayoderock

This comment has been minimized.

@ByungWookYe

This comment has been minimized.

Copy link

commented Mar 7, 2019

@kayoderock I guess my solution seems similar with your link, but More specifically work for vue init webpack prjName command.

vue init webpack prjName command create project with webpack.base.conf.js, webpack.dev.conf.js, webpack.prod.conf.js and that config files use generateLoaders function to setup style-loaders.

I just wrote that comment for less skilled persons like me :)

@kayoderock

This comment has been minimized.

Copy link

commented Mar 7, 2019

@ByungWookYe Alright, I get your point, I am just not sure if it's solving the problem here - having to load the sass at every needed point. Do you get me ?

@ByungWookYe

This comment has been minimized.

Copy link

commented Mar 7, 2019

@kayoderock yeah, It add @import "@/sass/vue-globals.scss"; for every sass codes or files ,just same as your linked solution, and thus it solved the problem.

@kayoderock

This comment has been minimized.

Copy link

commented Mar 7, 2019

Thats fine, @ByungWookYe it works too. Thanks.

@Secular12

This comment has been minimized.

Copy link

commented Mar 10, 2019

I am trying to create a Vue Component Library, where all of the components have a default scss variable in them, for example:

$component-name-color: #000 !default

The intention is that the components will have default styling that could easily be configured/overridden when I later install my component library as an npm module in another project but be able to override the styles in a configurable variables scss file. I can't seem to figure out on how to have the vue library's config file to accept that scss file in order to apply the "overrides". Or, to update the end projects vue config file to merge with the vue component's config file.

I apologize if this should be a separate issue. I ultimately chose not to since it is mostly related to this issue.

@jordanboston

This comment has been minimized.

Copy link

commented Apr 16, 2019

Thanks @nellysattari
This worked for me: https://css-tricks.com/how-to-import-a-sass-file-into-every-vue-component-in-an-app/ Since I had simply missed the part about restarting the dev server from other examples, but she mentions that in this article.

@nicolay-zlobin

This comment has been minimized.

Copy link

commented Apr 30, 2019

Nuxt Style Resources module helps me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.