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

[Question] – Sass @import globally available #149

Closed
silvestreh opened this issue Jun 3, 2016 · 20 comments
Closed

[Question] – Sass @import globally available #149

silvestreh opened this issue Jun 3, 2016 · 20 comments

Comments

@silvestreh
Copy link

Say I have a main app.scss which imports other things like color variables, a CSS reset, and Animate.css.

// app.scss
@import 'partials/colors';
@import 'vendor/normalize';
@import 'vendor/animate';

I then use this app.scss file in my main App.vue component.

<!-- App.vue -->
<template>
    <my-component></my-component>
</template>
<style lang="scss" src="./app.scss"></style>
<script>…</script>

How can I use those color variables and @extend Animate.css classes from within other components? For now I've resorted to @importing them all over again, but it's not a nice solution and (I think) it duplicates the code.

<!-- myComponent.vue -->
<template>…</template>
<style lang="scss">
.myComponent {
    @extend .animated; // fails unless I @import animate.css again.
}
</style>
<script>…</script>
@chrisvfritz
Copy link
Contributor

The forum or the Gitter chat are actually better places for questions like this, as we try to reserve the issues for feature requests and bug reports.

@gazpachu
Copy link

@chrisvfritz I think you should reconsider allowing this kind of questions too, as it is quite a relevant topic and with the labels, everything can be correctly tracked and organised.

@silvestreh did you manage to find a proper way of doing it?

@silvestreh
Copy link
Author

@gazpachu Nope, I ended up not worrying too much about it, especially with the partials that don't produce CSS output (like variables), I include those over and over again.

In the case of third party stuff, like Animate.css, or partials that do produce CSS output, I avoid @importing them within scoped styles because I'll end with duplicated code.

If you include partials that do produce CSS output, or third party stuff, within a regular <style> tag in your .vue component, duplicate code will be removed upon minification when you build your app for production environments.

@hal0gen
Copy link

hal0gen commented Jan 15, 2017

Apparently this looks like the only solution available, a long discussion about the same issue can be found here: vuejs/vue-loader#328

@gazpachu
Copy link

gazpachu commented Jan 15, 2017

I fixed it with one line of code in build/utils.js:
scss: generateLoaders(['css', 'sass?data=@import "~assets/styles/app";'])

Then, in src/assets/styles/app, you add all the @imports and voilà!

@hal0gen
Copy link

hal0gen commented Jan 15, 2017

@gazpachu That's fantastic, I confirm it works!

This is a common problem for people using vue-cli, I think it should be mentioned in the documentation. From what I understand, your answer is very relevant for the following issues:

You might also want to answer the following questions/issues (I'd do it myself but you solved the puzzle):

@gazpachu
Copy link

@hal0gen thanks. I've updated the stackoverflow thread but in the Vuejs forum, I can't sign-up/login, so if you can, please post it there. Thanks

@Fleeck
Copy link

Fleeck commented Feb 21, 2017

@gazpachu amazing, big thanks for this!

@grantcarthew
Copy link

grantcarthew commented Mar 1, 2017

Hi, I just want to add to @gazpachu answer above. I used a different syntax for my build/utils.js file like so:

  let sassOptions = {
    indentedSyntax: true
  }
  let scssOptions = {
    includePaths: [
      '~src/styles'
    ],
    data: '@import "~src/styles/main";'
  }

  // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', sassOptions),
    //  Make custom SASS available to all components https://github.com/webpack-contrib/sass-loader
    scss: generateLoaders('sass', scssOptions),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }

For reference, the sass-loader supports all node-sass options. So in the above code you can add any of those options to the scssOptions object.

@alexmccabe
Copy link

@grantcarthew for me this didn't work, but if it were to work, would this make variables defined in /styles/main global to be accessed by any .vue component?

I guess I need to play around more with my config.

@grantcarthew
Copy link

@alexmccabe When I posted that snippet above I didn't post the generateLoaders function. Checkout vue-foundation for a better example.

@lehni
Copy link

lehni commented Apr 12, 2017

@grantcarthew how do you get the ~ to work in your example? It doesn't work for me. The only way can get this to work currently is by doing this:

  let scssOptions = {
    includePaths: [
      // '~src/styles'
      path.resolve('./src/styles')
    ],
    // data: '@import "~src/styles/main";'
    data: `@import "~${path.resolve('./src/styles/main')}";`
  }

I should mention that I am on webpack 2. Could this be the reason?

@grantcarthew
Copy link

Hi @lehni. As stated in my last comment, see the vue-foundation template for reference. Here is the file with the answer for your question:

https://github.com/hal0gen/vue-foundation/blob/master/build/utils.js

@woshi82
Copy link

woshi82 commented Apr 25, 2017

I have found that the symbol ; is really important in @import "~${path.resolve('./src/styles/main')}";

@ppozniak
Copy link

Here's how I managed to get it work:

scss: generateLoaders('sass', {
      includePaths: ['./src/styles'],
      data: '@import "_main.scss";'
    }),

includePaths is an array of paths that will be looked at when you are doing @import
data is a thing, that will be inserted into every sass scope

@l2aelba
Copy link

l2aelba commented Jun 2, 2017

For LESS, I would do something like :

<style src="@/libs/css/global.less" lang="less"></style>
<style lang="less">
  @import (reference) "libs/css/global.less";
  #app {
    .my-custom();
  }
</style>

This will not be duplicate even .my-class or .my-class() on Less, Its will use just as reference

@lehni
Copy link

lehni commented Jun 14, 2017

Here how I have this working now for both Sass and Stylus:

  var sassOptions = {
    includePaths: ['./src/styles'],
    data: '@import "_main.scss";'
  }

  var stylusOptions = {
    paths: [path.resolve('./src/styles')],
    import: ['_main.styl']
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass',
        Object.assign({ indentedSyntax: true }, sassOptions)),
    scss: generateLoaders('sass', sassOptions),
    stylus: generateLoaders('stylus', stylusOptions),
    styl: generateLoaders('stylus', stylusOptions)
  }

@Love-the-fish-cat
Copy link

this way will create more css code,i use cssnano plugin and run npm run dev can't delete more css code.

@anish000kumar
Copy link

@percy507
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests