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>
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.
@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?
@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.
Apparently this looks like the only solution available, a long discussion about the same issue can be found here: https://github.com/vuejs/vue-loader/issues/328
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à !
@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):
@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
@gazpachu amazing, big thanks for this!
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.
@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.
@alexmccabe When I posted that snippet above I didn't post the generateLoaders function. Checkout vue-foundation for a better example.
@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?
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
I have found that the symbol ; is really important in @import "~${path.resolve('./src/styles/main')}";
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
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
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)
}
this way will create more css code,i use cssnano plugin and run npm run dev can't delete more css code.
Most helpful comment
@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?