Search code examples
reactjssasscreate-react-appcss-modules

Sass @use does not work in CSS modules in React, while import does


I have generated a React project with create-react-app using the TypeScript template. I've installed Sass via npm install sass, while CSS modules were already supported by the generated template.

I've created a common set of variables within the styles/common.scss file. I wanted to import and use the variables from the file in the stylesheet of my component. The recommended way to do this seems to be the @use directive, but I was unable to get to work.

Relevant files within my project structure:

components/
  custom/
    Custom.module.scss
    Custom.tsx
styles/
  common.scss

In this scenario components/custom/Custom.module.scss tries to import and use a variable from styles/common.scss with @use "styles/common.scss". While I don't get any specific errors related to the @use directive, attempting to reference any variables from the common stylesheet results in the following error: SassError: Undefined variable.

Things I've tried so far:

  • Proceeding the path with ~: @use "~styles/common.scss" yields the same error.
  • Different combinations of adding underscore to the common stylesheet, as well as removing extensions from the path in @use: same results.
  • Replacing @use with @import "styles/common.scss" works as expected: the variables are available in the CSS module.

However, since the @import is set to be deprecated, I'm wondering how to get @use to work and what is the root of the issue. Note that CSS modules themselves work as expected, and I'm able to import them correctly within the tsx files.


Solution

  • Given a default create-react-app setup, the correct way to import a module via @use is to omit the file extension (.scss) and the proceeding underscore. So, for example, styles/_colors.scss can be imported with @use "styles/colors".

    However, by default each variable (etc.) from the imported file will require a prefix to be used. So, for example, to reference $pink from the imported _colors.scss file, you'd have to write colors.$pink. To change the prefix, you can choose an alias with as in the @use directive. For example, @use "styles/colors" as c; would allow the variables to be accessed with a c. prefix. To remove the prefix altogether, use the * alias.

    Additionally, adding an _index.scss file allows using entire folders with specifying individual files. Use @forward directive in the _index.scss to choose which modules are available when importing the folder.

    So, to sum it up, the file structure should look roughly like this:

    • styles/_colors.scss
    $pink: #ff00ff;
    
    • styles/_index.scss: optional, allows importing multiple modules in 1 step.
    @forward "styles/colors";
    
    • components/custom/Custom.module.css
    @use "styles" as *;
    // Or: @use "styles/colors" as *;
    
    // Now $pink can be referenced without an alias.