DEV Community

Cover image for Sass modules with the Vue CLI
Josip Ivancic
Josip Ivancic

Posted on • Originally published at jivancic.com

Sass modules with the Vue CLI

The new sass modules are only compatible with Dart Sass which you should be using. More info can be found on the official sass-lang.com page.

See full example on repo: vue-cli-sass.

Not enough people are aware of the announcement of the new Sass module system, of which the primary aim is to replace the @import rule with @use and @forward. It also exposes various built-in modules such as sass:color, sass:map, etc. If you're wondering why you should use @use over @import, in short, @import is being replaced with more explicit @use and @forward rules, it forces you to a more complex setup but will be worth it in the long run, especially if you're building some kind of library or package. Over the next few years Sass @import will be deprecated, and then removed.

The @use rule

The @use rule makes variables, mixins, and functions from another stylesheet available in the current stylesheet. It pretty much does the same thing as @import, but with namespacing. Example from sass-lang.com:

@use "bootstrap";

.element {
  background-color: bootstrap.$body-bg;
  @include bootstrap.float-left;
}
Enter fullscreen mode Exit fullscreen mode

You can also explicitly set the namespace by using as.

@use "bootstrap" as b;

.element {
  @include b.float-left;
}
Enter fullscreen mode Exit fullscreen mode

To include everything in the top-level namespace, use the special * symbol.

@use "bootstrap" as *;

.element {
  @include float-left;
}
Enter fullscreen mode Exit fullscreen mode

The @forward rule

The other important feature of the module system is the @forward rule. It includes another module's variables, mixins, and functions without making them visible to the code within the current module. Basically, it makes it possible to organize across many files and load the styles from a single entry point file.

If you had multiple partial files in a components folder, you would @forward them through an _index.scss entry file. For example:

// components/_index.scss
@forward "buttons";
@forward "tags";
Enter fullscreen mode Exit fullscreen mode

Then you would @use the appropriate stylesheet (pointing to the folder automatically references the _index.scss file).

// styles.scss
@use components;
Enter fullscreen mode Exit fullscreen mode

To learn more about all the benefits and features introduced with modules, be sure to check out the official sass-lang.com website, there is also a great article on css-tricks.com.

Using it with Vue

Create a new project with the Vue CLI, if you don't have it installed go to vue-cli and follow the instructions given. We need to run:

vue create using-sass-modules # or whatever name you want
Enter fullscreen mode Exit fullscreen mode

After the prompt in the terminal, select manually select features and check the CSS pre-processor option. Choose the rest of the options by your project needs.

Directory structure

First, we will create a directory to hold our styles, I named mine styles. How you organize your directories is your business, but I like to use an architecture similar to the one described in sass-guidelines.es. Inside of styles, we'll have an abstracts, base and utilities folder and inside each one partial file which will be @forward-ed through an _index.scss entry file ending up with this structure:

src/styles
├── abstracts
│   ├── _breakpoints.scss
│   ├── _colors.scss
│   ├── _font.scss
│   ├── _index.scss
│   └── _mixins.scss
├── base
│   ├── _base.scss
│   ├── _index.scss
│   ├── _reset.scss
│   ├── _root.scss
│   └── _typography.scss
├── main.scss
└── utilities
    ├── _colors.scss
    ├── _index.scss
    └── _layout.scss
Enter fullscreen mode Exit fullscreen mode

The main.scss file will @use all our global styles. Obviously, you can adjust the files to your specific needs.

File structure

The contents of the entry files will be:

// abstracts/_index.scss
@forward "breakpoints";
@forward "colors";
@forward "font";
@forward "mixins";
@forward "variables";
Enter fullscreen mode Exit fullscreen mode
// base/_index.scss
@forward "reset";
@forward "root";
@forward "typography";
@forward "base";
Enter fullscreen mode Exit fullscreen mode
// utilities/_index.scss
@forward "colors";
@forward "layout";
Enter fullscreen mode Exit fullscreen mode

and inside main.scss. Notice we are not including abstracts since they wouldn't work inside components because of the scoped attribute.

// main.scss
@use "base";
@use "utilities";
Enter fullscreen mode Exit fullscreen mode

If we now @use the main.scss file in our App.vue, the styles should apply. However, if we try to use a mixin or a variable you'll notice we get an error since they aren't @use-d inside of our components.

Vue config

To handle this we will add a vue.config.js file which is a wrapper for webpack configuration. With the help of this, we can include variables and mixins into every component in order not to repeat ourselves with a @use statement inside each component. Learn more about the config file here.

module.exports = {
  css: {
    loaderOptions: {
      sass: {
        prependData: `@use '@/styles/abstracts/_mixins.scss' as *;`,
      },
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

I am only including the mixins here since my variables are defined as custom properties.

If you now @include a media query or use a sass variable inside of your components it should work!

// HelloWorld.vue
<template>
  <h1 class="h1 hello">Hello world</h1>
</template>

<script>
export default {
  name: "HelloWorld",
};
</script>

<style scoped lang="scss">
.hello {
  color: $primary;

  @include mq(small) {
    font-size: 7rem;
  }
}
</style>
Enter fullscreen mode Exit fullscreen mode

And the result is:

Hello World


Congratulations, you are now all set up for developing a large-scale application with well-organized and scalable stylesheets!

Top comments (0)