DEV Community

loading...
Cover image for How to import Sass/SCSS mixins global?

How to import Sass/SCSS mixins global?

Dennis Frijlink
React.js and Vue.js developer that loves learning new things
・1 min read

At the moment I'm working on a boilerplate based on React.js. In the assets folder I have a _mixins.scss and _breakpoints.scss file.

// ../assets/_breakpoints.scss

/* Small (sm) */
$screen-sm-min: 640px;

/* Medium (md) */
$screen-md-min: 768px;

/* Large (lg) */
$screen-lg-min: 1024px;

/* Extra Large (xl) */
$screen-xl-min: 1280px;

/* Two Extra Large (xxl) */
$screen-xxl-min: 1536px;

...
Enter fullscreen mode Exit fullscreen mode
// ../assets/_mixins.scss

// Medium devices
@mixin md {
    @media (min-width: #{$screen-md-min}) {
        @content;
    }
}

// Large devices
@mixin lg {
    @media (min-width: #{$screen-lg-min}) {
        @content;
    }
}

...
Enter fullscreen mode Exit fullscreen mode

I import the two .scss files in the App.js so I can access the classes/mixins/variables global. But only the classes are accessible.

So for example using a mixin in App.scss:

.container {
  background: red;

  @include md {
    background: green;
  }
}
Enter fullscreen mode Exit fullscreen mode

You should think this would work (defining a class in the _mixins.scss and using in the App.js file works) but he gives the error:

SassError: no mixin named lg

Anyone who is similar with this problem and maybe can help me?

Discussion (13)

Collapse
jwkicklighter profile image
Jordan Kicklighter

I'm sorry that I don't have a solution, but this post taught me about the @content feature of Sass. Thank you!

Collapse
dennisfrijlink profile image
Dennis Frijlink Author

Hey no problem. If have a nuxt boilerplate with the same structure as this react project: github.com/dennisfrijlink/nuxt-spa..., with the difference that it works.

The weird part of the story is, is that I can use the .css classes I define in the global .scss files in all the React Components but I can't use the global mixins/variables.

Collapse
jwkicklighter profile image
Jordan Kicklighter

If that's the case, I'm gonna take a stab at saying that it has to do with the way that the webpack pipeline is behaving. My guess is that in the nuxt version the sass isn't being compiled until after the component styles are stripped out of the .vue files, but in the react version the sass from .scss files is being compiled separately from the styles being stripped out of component files. I know that importing .scss into Vue components without a nuxt project used to take a bit of work.

Something you could try: import that global sass file right into the react component using @import "..."; and see what happens. In previous Vue projects, I did this instead of a global include and it worked well. Obviously it's much nicer to have a single, global import statement, but this could potentially help with troubleshooting.

Thread Thread
dennisfrijlink profile image
Dennis Frijlink Author

At first I wanna thank you for your support. Hopefully we can fix it.
Even when I make a .scss file for the root.js component the child components can't use the mixins. In the .README I explain the structure of the boilerplate: github.com/dennisfrijlink/react-sp.... Maybe you can take a look? Probably I miss something

Thread Thread
jwkicklighter profile image
Jordan Kicklighter

No problem! I'm admittedly not very familiar with most React development, but I use Sass and Vue regularly.

Even when I make a .scss file for the root.js component the child components can't use the mixins.

So what I'm suggesting for troubleshooting is: instead of relying on webpack to make your global mixins available, try explicitly importing the mixin file into the children files. So in the "For Example" snippet at the very bottom of the README, do this:

@import "path/to/mixins.scss";

.container {
 ...
Enter fullscreen mode Exit fullscreen mode
Thread Thread
dennisfrijlink profile image
Dennis Frijlink Author

Aaah okay. So if a component needs one or more mixins, defined in mixins.scss, I have to import it in the local .scss file of the component right? You maybe have an idea why only the breakpoints & mixins are not working? If I define for example a class in the main.scss file than I can use that class in every component without importing it every time.

Thread Thread
jwkicklighter profile image
Jordan Kicklighter

So if a component needs one or more mixins, defined in mixins.scss, I have to import it in the local .scss file of the component right?

I'm sure there is a way to avoid this in the long run, but from my experience this is at least a fairly easy way to get things working.

If I define for example a class in the main.scss file than I can use that class in every component without importing it every time.

To answer this, it's important to consider exactly what's going on mechanically, and how CSS works without even using Sass or any pre-processors. The goal of Sass is to use a language that supports more features than CSS, run that language through a processor, and generate a plain CSS file that can be handed to a browser. A "mixin" is a feature of Sass, there is no concept of it in CSS. So when you use a mixin, the Sass compiler actually has to know about the mixin definition, which means that the compiler needs the code in your file and the mixin code which, in this case, is in a separate file. Because Webpack is responsible for running your Sass through the Sass compiler, it seems that the compiler doesn't have access to the global mixins.scss file while compiling all of the other .scss files.

The other code, such as plain CSS classes, are being compiled in your root scss file and served to the browser. Your components are referencing these classes using class="my-root-class". This is exactly the same as going into the root of your HTML document, creating a <style> tag, and adding some classes there. Any class loaded into the browser is available anywhere on the page because CSS itself is inherently global.

The summary is that mixin problems are an issue with the compilation step (converting Sass to CSS), while using global CSS classes in any component is not related to Sass or the compilation step.

Thread Thread
dennisfrijlink profile image
Dennis Frijlink Author

That makes sense! So if I wanna use the mixins globally I have to configure the webpack right?

Thread Thread
jwkicklighter profile image
Jordan Kicklighter

That would be my guess about where the problem lies. If I'm not mistaken, doesn't the Next configuration actually have the global scss file declared somewhere? I believe this is imported into webpack's chain in a way that makes it available to the Sass compiler. So there should be some way to accomplish the same thing outside of Nuxt.

Thread Thread
jwkicklighter profile image
Jordan Kicklighter

Here is an answer in Stack Overflow that's discussing this exact problem (except variables instead of mixing) stackoverflow.com/a/35554536

Thread Thread
dennisfrijlink profile image
Dennis Frijlink Author

Alright. I will take a look at the configuration of webpack and I how I can fix the global .scss mixins. Thanks for your help and the explanation of sass + webpack! I will sign you if it works :)

Thread Thread
jwkicklighter profile image
Jordan Kicklighter

You bet, good luck!

Thread Thread
dennisfrijlink profile image
Dennis Frijlink Author

Hey Jordan,

First of all. Thanks for your support. After searching and testing I started to use CRACO (Create React App Configuration). CRACO is an easy and comprehensible configuration layer for create-react-app based on the structure of Webpack. It kinds of overwrites the rules of webpack you specify in the craco.config.js file. With the plugin craco-sass-resources-loader I managed to load a global SCSS file called utils.scss:

const sassResourcesLoader = require('craco-sass-resources-loader');

module.exports = {
  mode: "development",
  output: {
    path: __dirname
  },
  plugins: [
    {
      plugin: sassResourcesLoader,
      options: {
        resources: './src/assets/scss/utils.scss',
      },
    },
  ]
};
Enter fullscreen mode Exit fullscreen mode

In the utils.scss I simply import all the main SCSS files I wanna use (think of mixins, breakpoints etc.):

/* import scss utilities */
@import './breakpoints';
@import './mixins';
Enter fullscreen mode Exit fullscreen mode
Forem Open with the Forem app