@use & @forward in SASS
Tags: css, html, sass, scss
Published: 2021-05-12 11:50:19

I have been working with CSS over the years and love it. I have tried various libraries, toolsets like Bourbon (yes, I am that old), and pre-processors like SASS & Less.

Talking about the CSS pre-processors, lately, I was reading about how `node-sass` will be deprecated soon, and hence, I checked out the `dart-sass` documentation.

While reading the documentation, I came across an exciting way of importing the SASS files instead of the traditional way of importing the stylesheets using `@import` statements.

Yes, just like me, you must have thought the same, that what would be better than using `@import` statements to import the Stylesheets? Well, `dart-sass` has to offer two new ways of importing them, namely `@use` and `@forward`.

---

> Important: Make sure that you have [`sass`](https://www.npmjs.com/package/sass) installed, and NOT [`node-sass`](https://www.npmjs.com/package/node-sass)

Before we try out the new ways to handle the imports using SCSS, we will first define the Files & the Folder structure.

```
/project
|-- /vars
|---- _colors.scss
|---- _fonts.scss
|-- app.scss
```

---

## Let's try out @use

As you know, we can import the files in SCSS using the `@import` statement. `@use` pretty much does the same thing, EXCEPT, that it namespaces your variables, thus, preventing the name collisions.

Starting with some simple code here, we will create a file to hold some variables, and then we will require this in our App file.

```
// _colors.scss
$h1-color: #f00;
$component-color: #0f0;
```

And then, we will use `@import` first, in `app.scss` to test if everything's in place.

```
// app.scss
@import 'vars/colors';

h1 {
  color: $h1-color;
}
```

The above should work as expected. Now, without any further ado, we will go ahead and modify the `@import` statement to `@use`.

```
// app.scss
@use 'vars/colors';

h1 {
  color: $h1-color;
}
```

> @use helps you namespace your SCSS files

Now that we are using `@use` it to import the stylesheet will result in an error. Reason? Remember, in the beginning; I mentioned that `@use` helps us namespace our variable names, thus preventing collisions if any. Hence, we need to modify the above code like:

```
// app.scss
@use 'vars/colors';

h1 {
  color: colors.$h1-color;
}
```

Viola, the SCSS is now compiled. All we did was, prefixed the `$h1-color` variable using colors that are nothing but the file name.

---

## @use(ing) Alias

Now, what if we have a file name of `_colors_for_theme_blue.scss` (not pretty at all but assuming some worst-case scenario), and then writing it like `colors_for_theme_blue.$h1-color` will be super annoying.

To cut short the filename, you can use the keyword as that will help you create an alias for the `_colors.scss` file. E.g.:

```
// app.scss
@use 'vars/colors' as c;

h1 {
  color: c.$h1-color; //note that now we are using only c here
}
```

> `as` helps you define an alias for the file name you are importing using the `@use` keyword.

Alternatively, you could also use an `*` as an alias which will result in behavior similar to the one which `@import` provides. For, e.g.:

```
// app.scss
@use 'vars/colors' as *;

h1 {
  color: $h1-color; // note, you need not have to specify
                       colors prefix before you use $h1-
                       color variable.
}
```
I would not recommend you doing the above since it misses the point in having name-spaced variables.

---

## Scope using @use vs. @import

There is another benefit of using `@use` instead of the `@import` is the scope. When we use `@import` statement to import certain files, then this file has access to the declared variables before importing the component file. For, e.g.: (we will introduce a new folder here, say components, and create a sample component file like `_my_component.scss`)

```
/project
|-- /components
|---- _my_component.scss
|-- /vars
|---- _colors.scss
|---- _fonts.scss
|-- app.scss
```

Here, we will try to import **`_my_component.scss`** using the `@import` statement and then using the `@use` and see the difference.

```
// app.scss
// using @import
@import 'vars/colors';
@import 'components/_my_component';

h1 {
  color: $h1-color;
}
```

And here we have some code in the `_my_component.scss` file

```
// _my_component.scss
.my-component {
  color: $component-color;
}
```

In the above example, the code will be compiled as expected, where even the `_my_component.scss` has access to the variables declared in the `app.scss` file, create issues as the codebase grows.

The above results in the following compiled CSS

```
// compiled output
.my-component {
  color: #0f0;
}

h1 {
  color: #aaa;
}
```

If you notice, the `.my-component` can access the colors defined in a separate file imported before importing the component file.

If we make use of `@use` instead of the `@import`, here's what will happen.

```
// app.scss
// using @use
@use 'vars/colors' as c;
@use 'components/_my_component';

h1 {
  color: c.$h1-color;
}
```

Tweaking the component file a bit:

```
// _my_component.scss
.my-component {
  color: c.$component-color;
}
```

The above will result in an error:

> Error: There is no module with the namespace "c".

Say if we remove the namespace, which is c, then the error which we will get is

> Error: Undefined variable.

Hence, using `@use` helps you control the scope of your variables instead of `@import` which makes the variables globally accessible to the files which are imported post the variable file. Still, if you wish to use the same variable file in the `_my_components.scss` then you need to require the variables in the components file as well.

```
// _my_component.scss
@use '../vars/colors' as c; //note the filepath here,
                              have added ../

.my-component {
  color: c.$component-color;
}

.my-component {
  color: c.$component-color;
}
```

---

## Using @forward

You must be having multiple helper files, say for variables, mixins, fonts, extends, etc. Having to require them in every single file (since using `@use`, it will not make these files globally available) required in components and other SASS files will be tedious.

Hence, we could use `@forward` which acts like a pipe. It takes many files and makes the contents of those files available where this file is required. Let us take an example:

```
/project
|-- /components
|---- _my_component.scss
|-- /vars
|---- _colors.scss
|---- _fonts.scss
|---- helpers.scss // we will add this file here, which 
                      will contain forwards of 
                      _colors.scss & _fonts.scss
|-- app.scss
```

And now we will add the `@forward` to the `helpers.scss` file.

```
// helpers.scss
@forward 'colors';
@forward 'fonts';
```

Now instead of requiring every helper file in `app.scss` you would instead import the `helper.scss` which will make the other files like `_colors.scss` & `_fonts.scss` available.

```
// app.scss
@use "vars/helpers";
@use "components/my_component";

h1 {
  color: helpers.$h1-color; // note that you need to modify
                               the namespace, or use * and 
                               you could simply use $h1- 
                               color
}
```

and subsequently, we can now modify the `_my_component.scss` file as well.

```
// _my_component.scss
@use "../vars/helpers";

.my-component {
  color: helpers.$component-color;
}
```

Using `@forward` will make it simple for you to import multiple files without specifying them separately and instead use the common file.

---

The above is a basic intro for using `@use` and `@forward`. There is much more to it, like Private Members, Index Files, Visibility Control, etc. I'll be attaching a few references where you could refer to these features in detail.

## References

- Documentation for [@use](https://sass-lang.com/documentation/at-rules/use)
- Documentation for [@forward](https://sass-lang.com/documentation/at-rules/forward)
- [Dart SASS](https://sass-lang.com/dart-sass)
- [SASS NPM](https://www.npmjs.com/package/sass)