Getting Undefined variable error when compiling SCSS using node-sass - css

package.json
"scripts": {
"compile:sass": "node-sass sass/main.scss css/style.css -w"
}
main.scss
#import "abstracts/variables";
#import "base/typography";
_variables.scss
$color-light-grey: #777;
$color-white: #fff;
_typography.scss
body {
color: $color-light-grey;
}
.heading-primary {
color: $color-white;
}
Now my issue is when I'm trying to compile with npm run compile:sass it throws the following error:
"message": "Undefined variable: \"$color-light-grey\"."

convert all file names with beginning "_"
example:
typography.scss >> to >> _typography.scss

Looks like there are two errors in your code above:
You import "abstracts/variables" but, at least in the text, the file name seems to be _variables.scss (missing an "s")
You should import "abstracts/variables" before everything else.
Like that:
#import "abstracts/variables";
#import "base/typography";

Simply import everything in this order
- abstracts
- vendors
- base
- layout
- components
- pages
- themes

Related

Next.JS: Using SASS variables from global scss

I have a Next.js Application with a main.scss global css file imported in the pages/_app.js file.
_app.js
import '../global-styles/main.scss'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
The styles from this file work.
I also have some modular scss files attached to components, using [component].module.scss.
I have written a variable in my variables.scss file, one of the files which I #import in main.scss,
variables.scss
$mobile: 750px;
main.scss
#import './fonts.scss';
#import './variables.scss';
#import './global.scss';
However, when I try to use this variable in one my modular css, I get an error
./module-styles/navbar.module.scss (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-3-1!./node_modules/postcss-loader/src??__nextjs_postcss!./node_modules/resolve-url-loader??ref--5-oneOf-3-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-3-4!./module-styles/navbar.module.scss)
SassError: Undefined variable: "$mobile".
on line 19 of /Users/Parv/Documents/reactx/module-styles/navbar.module.scss
>> #media (max-width: $mobile) {
---------------------------^
My question is, why aren't my global variables which I declare in my main.scss coming through?
the easier way is to add a file with variable import and add alias to tsconfig
sassOptions: {
includePaths: ['./src'],
prependData: `#import "~#styles/variable.scss";`,
}
Update:
In file next.config.js need add this code (you need to create it if there is no such file)
module.exports = (phase, {defaultConfig}) => {
if ('sassOptions' in defaultConfig) {
defaultConfig['sassOptions'] = {
includePaths: ['./src'],
prependData: `#import "~#styles/variables.scss";`,
}
}
return defaultConfig;
}
In file tsconfig.json need add alias
"baseUrl": ".",
"paths": {
...
"#styles/*": [
"src/styles/*"
],
...
Then create file with styles on path: src/styles/variable.scss in variable.scss you can import other scss file
It is not related to Next.js, but to the way sass-loader works.
Each import of scss file from js file is treated as an isolated sass env, therefore, there is no such thing "global variables".
This behaviour requires you to import the variables.scss file from each scss file that uses one of the variables.
Side note, It is important that these common scss files (such your variables.scss) will not contain "regular" css, because if so, they will be duplicated many times (the amount of imports).
Just add this to your next.config.js file and restart
const path = require('path')
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `#import "main.scss";`
}
}
Apparently you can only import variables from a module file, not a global file.
Import variables.scss into your module's SCSS file, then import your variables from your module:
variables.scss:
$my-color = #123456;
:export {
myColor: $my-color;
}
page.module.scss:
#import './variables.scss';
page.jsx:
import color from './page.module.scss'
console.log(color.myColor); // '#123456'
This worked for me.
I solve it by adding my global variables to next.config.js. It is not a good solution but it works.
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
prependData: `
$primary-font-regular: 'Gotham';
$primary-font-medium: 'Gotham';
$default-font-size: 16px;
$h1: 5.208vw;
$h4: 1.458vw;
$primary-color: #000000;
$gray: #CCCCCC;
`,
},
};
You can follow this link for the answer: https://github.com/vercel/next.js/pull/12277

How can I get gulp-sass to compile bootstrap CSS definitions rather than just output the import statement?

I'm trying to pull in the Sass bootstrap source (.SCSS), make some customisations (via another .SCSS) and spit out a CSS file.
I've been trying to use Gulp to do this is VS2019 using gulp-sass. I've followed many tutorials and have come up with the following gulpfile.js
var gulp = require('gulp');
var sass = require('gulp-sass');
sass.compiler = require('node-sass');
gulp.task('sass', function () {
return gulp.src('./Main.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'));
});
In my Main.css I have the following:
$theme-colors: ( "primary": #fd7e14 );
#import "//lib/bootstrap-4.4.1/scss/bootstrap";
body {
color: #5CFF54;
background: rgb(92,18,18);
height: 400vh;
}
However, the file that is being generated contains the following:
#import "//lib/bootstrap-4.4.1/scss/bootstrap";
body {
color: #5CFF54;
background: #5c1212;
height: 400vh; }
I was expecting it to pull all of the individual styles into the produced CSS file, not just add the import.
Can anyone point me in the right direction?
After much trawling of the internet I have discovered that this is expected behaviour, and is down to the way I am referencing the source bootstrap.scss file.
In short, I am referencing it with web path, this has the effect of adding an import statement to the produced .css file. If I change the reference to a filesystem path such as this:
#import "../lib/bootstrap-4.4.1/scss/bootstrap";
it functions as I had hoped and the produced .css file includes all of the definitions from bootstrap.scss.

Can't compile material-components with webpack-encore

yarn encore dev fail after setting up material-components
I installed material-components using yarn add material-components-web --dev
and then configured app.js like this :
/* --- CSS --- */
import "../css/normalize.scss";
import "material-components-web/material-components-web.scss"
import "../css/layout.scss";
import "../css/style.scss";
/* --- RESOURCES ---*/
import $ from "jquery";
import * as mdc from "material-components-web";
When running yarn encore dev, I get the following error :
ERROR Failed to compile with 1 errors 22:30:40
error in ./node_modules/material-components-web/material-components-web.scss
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/sass-loader/lib/loader.js):
#import "#material/elevation/mixins";
^
File to import not found or unreadable: #material/elevation/mixins.
in /var/www/vhosts/salon-virtuel/node_modules/#material/button/_mixins.scss (line 23, column 1)
at runLoaders (/var/www/vhosts/salon-virtuel/node_modules/webpack/lib/NormalModule.js:301:20)
at /var/www/vhosts/salon-virtuel/node_modules/loader-runner/lib/LoaderRunner.js:367:11
at /var/www/vhosts/salon-virtuel/node_modules/loader-runner/lib/LoaderRunner.js:233:18
at context.callback (/var/www/vhosts/salon-virtuel/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
at Object.render [as callback] (/var/www/vhosts/salon-virtuel/node_modules/sass-loader/lib/loader.js:52:13)
at Object.done [as callback] (/var/www/vhosts/salon-virtuel/node_modules/neo-async/async.js:8077:18)
at options.error (/var/www/vhosts/salon-virtuel/node_modules/node-sass/lib/index.js:294:32)
# ./assets/js/app.js 7:0-62
Entrypoint app [big] = runtime.js vendors~app.js app.css app.js
error Command failed with exit code 2.
Imports in files :
node_modules/material-components-web/material-components-web.scss
#import "#material/elevation/mdc-elevation";
node_modules/#material/elevation/mdc-elevation.scss
#import "./mixins";
#include mdc-elevation-core-styles;
node_modules/#material/elevation/_mixins.scss
#import "#material/feature-targeting/functions";
#import "#material/feature-targeting/mixins";
#import "#material/theme/variables";
#import "./variables";
Any idea about why it's happening, and how to fix this?
I think you are very close. Try to edit your encore config to include node_modules to sass loader like this:
// enables Sass/SCSS support
.enableSassLoader(function(options) {
// https://github.com/sass/node-sass#options
options.includePaths = ['./node_modules'];
}, {
// set optional Encore-specific options
// resolve_url_loader: true
});
explained here
For the case, someone else stumbles over this.
It may would have also solved your issue, if you changed the way how you import the scss/sass files.
#import "~#material/feature-targeting/functions";
#import "~#material/feature-targeting/mixins";
#import "~#material/theme/variables";
#import "./variables";
The ~ references the node_modules as well. That is at least how I do it and it works without any special config for the sass-loader.

Extending bootstrap in create react app

I am tyring to extend boostrap classes in my sass file. I'm compiling my sass as in this example.
I have copied the boostrap files into my /src folder.
However, using this basic example:
#import "bootstrap/*";
.header{
#extend .container;
background-color:red;
}
I get the error:
{
"status": 1,
"file": "C:/sites/mharrisweb-redux/src/sass/style.scss",
"line": 1,
"column": 1,
"message": "File to import not found or unreadable: bootstrap/.\nParent style sheet: C:/sites/mharrisweb-redux/src/sass/style.scss",
"formatted": "Error: File to import not found or unreadable: bootstrap/.\n Parent style sheet: C:/sites/mharrisweb-redux/src/sass/style.scss\n on line 1 of src/sass/style.scss\n>> #import \"bootstrap/*\";\n ^\n"
}
If you have this file structure:
src
bootstrap
sass
style.scss
You should use:
#import "../bootstrap/scss/bootstrap";
If you installed Bootstrap using package manager (npm or yarn), you could use:
#import "~bootstrap/scss/bootstrap";

Cannot import 'font-awesome/scss/variables' in local SCSS module

I have Font Awesome v4.7.0 installed and I'm trying to write Sass classes that extend Font Awesome icon classes, like this:
div.edit-icon {
#extend .fa-pencil-square-o;
font-size: $icon-font-size;
}
At the start of one of my SCSS files (_shared.scss), I try importing the bare essentials I need from Font Awesome (installed in node_modules):
#import '~font-awesome/scss/variables';
#import '~font-awesome/scss/mixins';
#import '~font-awesome/scss/icons';
However, Webpack gives me this error when I save the file:
ERROR in ./~/sass-extract-loader!./app/views/components/_shared.scss
Module build failed: Error: File to import not found or unreadable: ~font-awesome/scss/variables.
Parent style sheet: C:/Users/<me>/WebstormProjects/<project>/app/views/components/_shared.scss
at options.error (C:\Users\<me>\WebstormProjects\<project>\node_modules\node-sass\lib\index.js:291:26)
# ./app/views/components/candb/MessageDefinitionView/CoreMessageDefinitionView.tsx 9:28-77
# ./app/views/components/candb/MessageDefinitionView/TxMessageDefinitionView.tsx
# ./app/views/components/candb/index.ts
# ./app/views/components/index.ts
# ./app/views/layouts/Page/Page.tsx
# ./app/routes.tsx
# ./app/index.tsx
# multi (webpack)-dev-server/client?http://localhost:1212 webpack/hot/dev-server react-hot-loader/patch webpack-dev-server/client?http://localhost:1212/ webpack/hot/only-dev-server ./app/index.tsx
Here's the start of node_modules\font-awesome\scss\_variables.scss:
// Variables
// --------------------------
$fa-font-path: "../fonts" !default;
$fa-font-size-base: 14px !default;
$fa-line-height-base: 1 !default;
//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly
$fa-css-prefix: fa !default;
$fa-version: "4.7.0" !default;
$fa-border-color: #eee !default;
$fa-inverse: #fff !default;
$fa-li-width: (30em / 14) !default;
What I noticed is that the value of $fa-css-prefix is an unquoted string (fa), and that commenting out this assignment allows this SCSS file to compile.
How is it legal for this string to be unquoted, and what can I do to allow me to import this SCSS file?
For reference, this is a relevant part of my Webpack config for loading SCSS modules:
// Add SASS support - compile all other .scss files and pipe it to style.css
{
test: /^((?!\.global).)*\.scss$/,
loader: extractModuleCSS.extract({
fallback: 'style-loader',
use: [
'css-loader?modules&sourceMap&camelCase&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'sass-loader'
]
})
}
Edit
I thought that the fact that Webpack displayed an error about a different file when I commented out $fa-css-prefix: ... meant that at least _variables.scss was compiling fine:
Undefined variable: "$fa-css-prefix".
in C:\Users\<me>\WebstormProjects\<project>\node_modules\font-awesome\scss\_icons.scss (line 4, column 4)
Apparently that isn't the case, though. If I comment out the other imports in _shared like this:
#import '~font-awesome/scss/variables';
//#import '~font-awesome/scss/mixins';
//#import '~font-awesome/scss/icons';
Then I still see the original error ('File to import not found or unreadable: ~font-awesome/scss/variables.') regardless of the changes I make to _variables.scss - even commenting out the entire file.
I've updated the title to reflect this new information.
Edit 2
Based on #CloudTseng's advice I tried this:
$fa-css-prefix: 'fa';
#import '~font-awesome/scss/variables';
#import '~font-awesome/scss/core';
#import '~font-awesome/scss/icons';
$icon-font-size: 16px;
div.edit-icon {
#extend .fa;
#extend .fa-pencil-square-o;
font-size: $icon-font-size;
}
div.cross-icon {
#extend .fa;
#extend .fa-times;
font-size: $icon-font-size;
}
Surprisingly, this gives me exactly what I want. The reason I find this surprising is that apparently I only needed to redefine fa-css-prefix locally - I was expecting that I would have to redefine all the Font Awesome variables from _variables.scss if I went this route.
However, inspecting my generated CSS shows me that all the other variables are magically resolved without me needing to redefine them:
font-awesome/scss/_icons.scss:
.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
.#{$fa-css-prefix}-music:before { content: $fa-var-music; }
.#{$fa-css-prefix}-search:before { content: $fa-var-search; }
...
/dist/modules.css:
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.app-views-components-candb-FieldDefinitionTable-___FieldDefinitionTable__fa-glass___2rm6a:before {
content: "\F000"; }
.app-views-components-candb-FieldDefinitionTable-___FieldDefinitionTable__fa-music___3q-Vg:before {
content: "\F001"; }
.app-views-components-candb-FieldDefinitionTable-___FieldDefinitionTable__fa-search___f89bE:before {
content: "\F002"; }
...

Resources