DEV Community

Cover image for My SCSS setup within a Vue CLI 3 project
Lynne Finnigan
Lynne Finnigan

Posted on • Updated on

My SCSS setup within a Vue CLI 3 project

I never realised that I had lost some of my passion for development until Vue.js came along. I'm still learning, but it has made coding fun again for me. I've played with it on and off for a little while, and now I'm working on building my own website from scratch again using Vue.

One of the hardest things to get my head around was the project structure. It's something not very many tutorials cover. Eventually I pieced it together, and came across my next problem. SCSS.

I couldn't find a lot of information on how people usually handle their use of global styles, and also styles within each component. I had an idea of how I wanted to do it, but no idea how to actually achieve it. If you're in a similar situation, I hope this article helps in some way.

So here's how I create a Vue CLI 3 app from scratch...

Creating the app

Assuming you have Vue CLI 3 installed, run the following command in the terminal to launch the Vue Project Manager in your browser.

vue ui
Enter fullscreen mode Exit fullscreen mode

If you don't have it installed yet, here is the documentation you need.

To create an app, simply click the create button at the top of the screen in the Vue Project Manager. This will then take you through various steps which you would normally have to do in the terminal, and allow you to save your settings as a preset. Handy!

For my projects I tend to choose the following options:

  • Package manager: Yarn
  • Preset: Manual (for the first project)
  • Features: Babel, Router, CSS Pre-processors, Linter/Formatter
  • History mode: on
  • Pre-processor: SCSS/SASS
  • Linter/Formatter: ESLint + Prettier (Lint on save)

Then click Create Project and it will create your app. You should now have a basic Vue.js project. You can run this by going to the tasks tab in the Vue Project Manager and clicking on serve to launch your site locally.

Setting up our styles

First of all, create a folder within the src folder named styles. This is where we will store all of our SCSS for the app. In this folder, create a file that will be used for your global styles e.g. global.scss

In the Vue Project Manager, go to the Plugins tab and click on the Add plugin button. We want to install a plugin called vue-cli-plugin-style-resources-loader.

Once this has installed, it will add a file to the root of your project called vue.config.js

Go to vue.config.js and add the following code, replacing the stylesheet name/path with whatever you have named your scss file for your global styles.

const path = require("path");

module.exports = {
  pluginOptions: {
    "style-resources-loader": {
      preProcessor: "scss",
      patterns: [path.resolve(__dirname, "./src/styles/global.scss")]
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Now, all of the styles from global.scss will be available across the project and within components. Normally my SCSS file structure looks something like this to begin with:

Image of scss file structure

I have basic rich text styles within _base.scss, and variables, typography, etc are all stored in their respective folders as partials. These are then imported into the global stylesheet like this:

@import "setup/normalize.scss";
@import "setup/typography.scss";
@import "setup/variables.scss";
@import "setup/mixins.scss";

@import "basics/base.scss";
@import "basics/layout.scss";
@import "basics/links.scss";
@import "basics/buttons.scss";
Enter fullscreen mode Exit fullscreen mode

I also have a folder within the styles directory for components. Each component I create in Vue will have it's own scss partial. A useful feature of Vue.js is that you can add styles within the Vue component file, and these can be scoped so that they will only render if that specific component is rendered on the page.

Now that we're all set up, adding styles to a component is easy. Here is how it would look in my component Example.vue

<template>
  <div>
    <h1>I am a component!</h1>
  </div>
</template>

<script>
export default {
  name: Example
}
</script>

<style lang="scss" scoped>
@import "../styles/components/example.scss";
</style>

Enter fullscreen mode Exit fullscreen mode

Inside the _example.scss file you would have access to all the variables/typography/mixins and anything else you have added in your global styles. You could also write it out inside the style tag like this, with $c-title being our global variable name for the title colour:

<style lang="scss" scoped>
h1 {
  color: $c-title;
}
</style>

Enter fullscreen mode Exit fullscreen mode

However, I prefer to keep all of the styles in one place overall (the styles folder & sub folders), with the file names named the same as the component itself. This makes it easier to find and for other people to work with.

This has been a long(ish) article, so if you've made it this far, thanks for reading! I hope this helps in some way. Have fun with your Vue projects and create something awesome!

Oldest comments (55)

Collapse
 
cychainey profile image
Cy Chainey

Really good article, I followed a similar pattern on a React project recently, the only difference is I used SCSS nesting to handle the encapsulation. I've been intrigued by the import style so thanks for the reminder/motivation to have a look.

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Awesome! :)

Collapse
 
peter profile image
Peter Kim Frank

Great article, and I feel like you should get bonus points for the META cover_image.

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Haha I wondered if anyone would notice! 😂

Collapse
 
karlwilbur profile image
Karl Wilbur • Edited

I totally get how one could lose their passion for develop. I've been at it for decades and sometimes it gets old. You've inspired me give Vue a shot and I'm excited about getting started this weekend. Thanks!

BTW, I love that you wrote this article in Markdown.

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Thanks Karl 😊

That’s great! Glad you’re going to give Vue a try, I’ve really enjoyed working with it so far. Let us know how you find it!

Collapse
 
dreamemulator profile image
dreamEmulator

Nice read, I like how there are so many people reigniting there passion for programming with Vue. Ultimately it's this passion that will help Vue end up on top. ♥️ Vue

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Thanks! I completely agree, many people have said this to me as well. Very nice to work with, great documentation and community.

Collapse
 
drozerah profile image
Drozerah

Well done ! Your article works perfectly even in France ! :) Next step for me, import a CSS+SASS grid micro-framework like KNACSS

Thanks Lynne !

Collapse
 
lynnewritescode profile image
Lynne Finnigan

I'm glad it has helped! Good luck :)

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Haha thanks! Well, I’ve never seen us both in the same room, so maybe I am you 😄

Collapse
 
deiknymi profile image
Akash Kumar Verma

Why import example.scss again in components when using global import already. I like to import all my general styles in vue.conf.js, then it is available inside every component without importing anything.

Collapse
 
lynnewritescode profile image
Lynne Finnigan

The idea is that your global styles are only variables and things you need access to globally. When you import example.scss it has the attribute ‘scoped’, which means it’ll only render if that component is rendered on the page. Saves you loading a larger css file with css that isn’t being used. Hope this helps!

Collapse
 
jinwoochu profile image
ossDev.jw

very good!!

Collapse
 
lateek35 profile image
Allan Raquin • Edited

Nice article :), however I was wondering if it could generate again and again all the styles called in global.scss each time a component has a <style scoped>. For exemple, the normalize.scss would be appended multiple time in the final file.

At least it seems to be the case when I replicate the exemple.

Here the compiled result:

/*! normalize.css v7.0.0 | MIT License html{line-height:1.15; [...]
/*! normalize.css v7.0.0 | MIT License html[data-v-abd815be]{line-height:1.15; [...]
/*! normalize.css v7.0.0 | MIT License html[data-v-jh6khva]{line-height:1.15; [...]

Or maybe this architecture should only be used with variables, mixins, functions ?

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Hey Allan, great question!

My thinking around this was that inside the global.scss, it would only really import variables and mixins / placeholders - basically anything that the scoped components might need to reference or need access to.

You could probably also just list those files in the config, instead of creating a global.scss file - I just preferred it that way.

You bring up a good point, I think a good way of tackling this would be to have just variables and things that your components need to reference in the vue config file, and then any other 'global' styles such as basic html / body / normalize files could be imported into your layout / wrapper vue file.

What do you think?

Collapse
 
lateek35 profile image
Allan Raquin

Yes, I ended up with this solution so far :).

I created an import.scss for all my variables and mixins / placeholders used with the style-resources-loader plugin, and imported the global css part with a simple import in my main.js file.

I think it give the best of both worlds if you want to write style scoped and also use some general (unscoped) style like a reset, normalize, general UI, etc.

Thread Thread
 
lynnewritescode profile image
Lynne Finnigan

Great! Yeah that is always the case for me, I always have sort of base styles that apply globally, but I want to scope all my components. So doing it this way works perfectly :)

Thread Thread
 
peoray profile image
Emmanuel Raymond • Edited

Hey Allan and Lynne, Sorry, kinda lost here :) Can you explain what you did to solve this? Especially with the import.scss file

Although, I think maybe importing the global.scss file in App.vue might also be a good solution?

Thread Thread
 
lynnewritescode profile image
Lynne Finnigan

Hi Emmanuel, the import.scss file should just have things like variables and mixins that the other files will need access to. If you don't use the plugin to serve the variables etc, you can't access them and use them within other components.

Thread Thread
 
peoray profile image
Emmanuel Raymond

So basically, from your example. Everything imported in the global.scss file is available to use in all the components?

Thread Thread
 
seanrparker profile image
Sean

Awesome post Lynne. This helped me clean up way too many double imports.

Emmanuel, I was a little confused too.

For the stylesheet that you call into vue.config.js only import mixins and variables (no style selectors/rules).

Call other global.scss (declared rules and stuff) elsewhere, like main.js or a parent app like App.vue.

Any style rules imported to a stylesheet through vue.config.js will import again for each component that uses it.

Collapse
 
phillfelix profile image
phillfelix

Really good article. I've been struggling with this for a couple of days and finally made it work, thanks!

Collapse
 
lynnewritescode profile image
Lynne Finnigan

No problem, I'm glad it helped 😊 I was in the same situation, and it took a while to figure out!

Collapse
 
shakilzaman87 profile image
Shakil Zaman

I make a CRM with Vue.js & Firebase. Checkout the demo here.
codecanyon.net/item/puku-crm/22205914?

Collapse
 
vertcitron profile image
Vert Citron

I have in a project a huge components base. Some have their style tag in scss, and others in sass.

When I put scss in 'preProcessor', it works for scss styles but not sass ones. If I put sass, the same, it does not works foe scss components.

Is there a way to import my variables file in both componetns ?

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Off the top of my head, it could be the import syntax. I think in scss it looks like this:

<style scoped lang="scss">
    @import 'styles.scss'
</style>

and in sass like this (without the quotes):

<style scoped lang="sass">
    @import styles.scss
</style>
Collapse
 
lynnewritescode profile image
Lynne Finnigan

Thanks, I'm really glad this helped you! 😊

Collapse
 
hjelperne profile image
hjelperne • Edited

Hi - a newbie question here - if anyone can please fill me in:

Following your guide I have successfully added vue-cli-plugin-scss-base (0.1.10) to my vue project.
And when using the "vue ui" (Vue Project Manager in your browser) approach - the scss folder with all the scss files get generated (as well as changes to vue.config.js and App.vue).

I suppose this happens just about the time the terminal which I engage "vue ui" from reports:
"🚀 Invoking generator for vue-cli-plugin-scss-base...
✔ Successfully invoked generator for plugin: vue-cli-plugin-scss-base
The following files have been updated / added:" (and the list of files: src/scss/animations/_animations.scss etc.......)

Now the question is: How would I go about doing this from the terminal??

I mean: "npm i vue-cli-plugin-scss-base" adds the statements to package.json and package.lock.json (in dependencies)

And "npm i vue-cli-plugin-scss-base --save-dev" adds to devDependencies (same as vue ui - from browser) when I add the plugin there..

but after that npm install / npm build / (rebuilding entire project in IntelliJ) or whatever I tried - it doesn't seem to have any effect. The scss file creation and file changes (mentioned above) never appear/happens.

Surely there is some essential command (knowledge) I am completely missing.

NEVER mind - the solution was as simple as: "vue add vue-cli-plugin-scss-base"

best regards,
H

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Hi, I was just about to look into this, did you get it all sorted then?

Collapse
 
secular12 profile image
Mark Dekin

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

$color: #000 !default

The intention is that the component will have default styling that could easily be configured/overridden when I later install my component library but 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.

Any insights?

Collapse
 
lynnewritescode profile image
Lynne Finnigan

Hi Mark, do you have a code example of the config file and where you're trying to add the scss?

I'd imagine that you could probably override based on the order you're importing the scss files into the component, but I'm not sure I understand what you're looking to do.