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

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.

Related

Selector ":root" is not pure (pure selectors must contain at least one local class or id) - NextJS with SASS modules

I've recently been switching to using modules in my next.js project, but I keep receiving this error in my newly created .module.scss files: "Selector ":root" is not pure (pure selectors must contain at least one local class or id)". I know this is because I'm not using pure css selectors as I've seen elsewhere online, and the only problem is the imports that I'm using, but I need those imports for variables like $cl-light-gray as seen below in this example file:
#import "src/common/styles/global-styles.scss";
#import "node_modules/bootstrap/scss/bootstrap";
#import "src/common/styles/palette.scss";
#import "src/common/styles/typography.scss";
.dashboard-dropdown-hover {
#extend .px-1;
#extend .py-2;
#extend .mt-3;
border: 1px solid transparent;
border-radius: 8px;
transition: 200ms;
background-color: transparent;
}
.dashboard-dropdown-hover:hover {
background-color: $cl-light-gray;
}
Does anyone have a solution to how I should fix this import problem? I know that if I switch back to .scss it will work, but I'm trying to avoid importing all the .scss files in _app.tsx because that would be at least 30 imports and also these styles aren't intended to be global. Lastly, why does Next.js expect me to use pure css selectors when I'm using Sass, which is used because of its non-pure elements?
After scouring the internet for a few hours I found a great solution from here: https://dhanrajsp.me/snippets/customize-css-loader-options-in-nextjs
EDIT: If you're using Next.js 12, check the bottom of the article above, because the solution is a little different.
You'll want to change your next.config.js file to include the following:
/** #type {import('next').NextConfig} */
require("dotenv").config();
const regexEqual = (x, y) => {
return (
x instanceof RegExp &&
y instanceof RegExp &&
x.source === y.source &&
x.global === y.global &&
x.ignoreCase === y.ignoreCase &&
x.multiline === y.multiline
);
};
// Overrides for css-loader plugin
function cssLoaderOptions(modules) {
const { getLocalIdent, ...others } = modules; // Need to delete getLocalIdent else localIdentName doesn't work
return {
...others,
localIdentName: "[hash:base64:6]",
exportLocalsConvention: "camelCaseOnly",
mode: "local",
};
}
module.exports = {
webpack: (config) => {
const oneOf = config.module.rules.find(
(rule) => typeof rule.oneOf === "object"
);
if (oneOf) {
// Find the module which targets *.scss|*.sass files
const moduleSassRule = oneOf.oneOf.find((rule) =>
regexEqual(rule.test, /\.module\.(scss|sass)$/)
);
if (moduleSassRule) {
// Get the config object for css-loader plugin
const cssLoader = moduleSassRule.use.find(({ loader }) =>
loader.includes("css-loader")
);
if (cssLoader) {
cssLoader.options = {
...cssLoader.options,
modules: cssLoaderOptions(cssLoader.options.modules),
};
}
}
}
return config;
},
};
I'm not seasoned with webpack or how it exactly works, but this solution worked for me. You can also change the regex to include css by doing (scss|sass|css) if you want.
As pointed out here, there is another option: you can import those styles in the global.css file. If you do that, Nextjs will be happy.
Any global styles (e.g., :root or any HTML elements/CSS classes that you want to have the same style absolutely everywhere in your app) should be placed into a global CSS file that you import into _app.js (which you just can add to the root folder of your project, if it doesn't already exist).
This global CSS file is also where you want to import any fonts that you will use app-wide.
Step-by-step instructions here: https://nextjs.org/docs/basic-features/built-in-css-support
In my particular case i was having the same headache with that issue, and was because i was trying to import the file with the path:
/node_modules/bootstrap/scss/bootstrap-utilities.scss
and that file was importing another file called _root.scss which was defined a selector in this style.
:root{
}
for solution that error i simply import the specific files used for my requirements
Another resources could help you:
https://www.youtube.com/watch?v=dOnYNEXv9BM&t=1044s
https://sass-lang.com/documentation/modules
https://dev.to/mr_ali3n/use-forward-in-sass-2bab

Gulpfile: How to compile each SCSS into separate CSS with same name but with additional common styles

First of all I'd like you guys to be gentle. I haven't been coding much in recent year and since gulp update when then changed syntax to writing functions and exporting I somehow made it work then and left with no changes up to this point, no clue if they changed something else. I've been happy with what it is right now, but I have no idea how to make it work the other way.
So anyway I'm working on a project right now, where there will be many htmls, and each one will have quite different styles, but some will be common. I want to make a main.scss file with common styles for each html, but I want to make a separate scss with styles specific to each html. This way in the end I want to have a separate css file made from a specific scss with same name combined with main.scss, so that it won't have to download a single large file, but only styles I need.
Example:
main.scss
01.scss
02.scss
03.scss
will compile to:
01.css ( main.scss + 01.scss )
02.css ( main.scss + 02.scss )
03.css ( main.scss + 03.scss )
This is my gulpfile right now:
const gulp = require('gulp');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
function style() {
return gulp.src('./scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'))
.pipe(browserSync.stream());
}
function watch() {
browserSync.init({
server: {
baseDir: './'
}
});
gulp.watch('./scss/**/*.scss', style);
gulp.watch('./*.html').on('change', browserSync.reload);
gulp.watch('./js/**/*.js').on('change', browserSync.reload);
}
exports.style = style;
exports.watch = watch;
If you have an idea how to do it in a better way I would really appreciate it.
I think you will have to import your main.scss into each of your other files and exclude main.scss from your gulp.src.
function style() {
return gulp.src(['./scss/**/*.scss', '!./scss/**/main.scss'])
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'))
.pipe(browserSync.stream());
}
'!./scss/**/main.scss' this negates or excludes that file from being passes into this task - I assumed main.scss was in the same folder as your other scss files, if that is not the case you will have to modify the path.
Then #import main.scss into each of your 01.scss, 02.scss, etc. files:
#import "main.scss"; // also assumes in same folder
You can put this import statement anywhere in the file, if it is first any of main.scss styles will be overridden by conflicting styles in the rest of the 0x.scss file. If you put the import statement at the end, then main.scss styles will override any previous conflicting styles.
Note: you should really be using #use instead of #import and gulp-dart-sass instead of gulp-sass at this point. See sass #use rule.
// in your gulpfile.js
const sass = require('gulp-dart-sass'); // once installed
#use "main.scss"; // must be at top of each scss file, such as 01.scss

Best way to have global css in Vuejs

What is the best way to have a global css file in Vuejs for all components? (Default css like bg color, button styling, etc)
import a css file in the index.html
do #import in main component
put all the css in the main component (but that would be a huge file)
Import css in your index.html, but if you're using webpack you can just import your stylesheets in your main js config and all your components will get the css.
As comments below suggested if using webpack adding this to main.js works:
import './assets/css/main.css';
I found the best way is to create a new file in the assets folder, I created as global.css but you can name anything of your choice. Then, import this file global.css file in the main.js.
Note: Using this approach you can also create multiple files if you think the global.css is getting really large then simply import all those files in the main.js.
#\assets\global.css
/* move the buttons to the right */
.buttons-align-right {
justify-content: flex-end;
}
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './routes'
Vue.config.productionTip = false
// Importing the global css file
import "#/assets/global.css"
new Vue({
router,
render: h => h(App)
}).$mount('#app')
In App.vue you can add a style property to declare you CSS file:
<style>
#import './assets/css/global.css';
</style>
You can also do something like this: https://css-tricks.com/how-to-import-a-sass-file-into-every-vue-component-in-an-app/
My folders are mostly structured like this:
- src
- assets
- _global.scss
- _colors.scss
- _fonts.scss
- _paragraphs
- index.scss // <-- import all other scss files.
This also works with normal css.
create a new css file in your assets folder for example : global.css
import "global.css" to main.js
import '#/assets/main.css';
There are to two ways, as I know, to achieve this.
Approach 1
Utilize vue.config.js configuration, less config can also be replaced with sass:
module.exports = {
css: {
loaderOptions: {
less: {
additionalData: `#import '#/style/common.less';`
}
}
}
}
Approach 2
In your .vue file, make your style looks like this:
<style lang="less">
#import (reference) "../../style/variables.less";
#app {
background: #bgColor;
}
</style>
Note: the (reference) flag is used to make variables defined in variables.less take effect. If you don't have variables, #import "../../style/variables.less"; is sufficient to do the trick.
For your reference, you can also take a look at this link:
https://github.com/tjcchen/vue-practice/tree/master/multipage-app
Sass announced their new module system. Why don't you use #use and #forward?
My approach is the best way to use scss with vite.
Use defineConfig to setup global scss (colors, mixin) and reuse in all component without import
css: {
preprocessorOptions: {
scss: {
additionalData: `#use "~/styles/main.scss" as *;`,
},
},
},
Here: code sandbox
create a vue.config.js file in your root directory
Create a styles folder inside your src folder and you can create your global style file here for example base.scss
to use scss install two dependencies
npm install node-loader sass-loader
Inside your vue.config.js paste code from below
module.exports = {
css: {
loaderOptions: {
sass: {
additionalData: `#import "#/styles/base.scss";`
}
}
}
};

Gulp Sass Bourbon, Not give me style.css

I have the problem, is went I run the task, everything is ok, but never give me the style.css result or output.
var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
sass = require('gulp-sass'),
compass = require('gulp-compass'),
neat = require ('node-neat').includePaths,
bourbon = require('node-bourbon');
// Bourbon Compile
gulp.task("compileBourbon", function(){
gulp.src('./src/sass/bourbon.scss')
.pipe(sass({
includePaths: require('node-bourbon').includePaths,
style: 'compressed',
quiet: true
}))
.pipe(gulp.dest('./builds/development/css'));
});
Bourbon is a mixin & function library so simply using it won't actually output any code, similar to how defining a function doesn't actually run the function. Neat is the same way, it only defines things that can be called but doesn't actually make any code by itself.
You'll want to #import "bourbon"; and #import "neat"; and then write css that uses the imported libraries likeā€¦
// mystyles.scss
#import "bourbon";
.my-class {
#include position(relative, 5em 2em null null);
color: blue;
}
As a side note, you probably don't want to be importing/using bourbon and compass at the same time. There is a bit of over lap and weird things can happen if you use them both.

How to compile SASS files in different directories using Gulp?

I'm using gulp-ruby-sass to compile my js and sass.
I ran into this error first TypeError: Arguments to path.join must be strings
Found this answer and it was because I was using sourcemaps with gulp-sass and the answer recommended using gulp-ruby-sass instead.
Next I tried to compile all my SASS files using this syntax:
gulp.task('sass', function () {
return sass('public/_sources/sass/**/*.scss', { style: 'compressed' })
.pipe(sourcemaps.init())
.pipe(concat('bitage_public.css'))
.pipe(sourcemaps.write('./maps'))
.pipe(gulp.dest('public/_assets/css'))
.pipe(livereload());
});
Which produced this error:
gulp-ruby-sass stderr: Errno::ENOENT: No such file or directory - public/_sources/sass/**/*.scss
I then noticed in the answer I found the author wrote that globes ** aren't supported yet:
Also keep in mind, as of this writing when using gulp-ruby-sass 1.0.0-alpha, globs are not supported yet.
I did more digging and found a way to use an Array to specify the paths to my SASS files, so then I tried the following:
gulp.task('sass', function () {
return sass(['public/_sources/sass/*.scss',
'public/_sources/sass/layouts/*.scss',
'public/_sources/sass/modules/*.scss',
'public/_sources/sass/vendors/*.scss'], { style: 'compressed' })
// return sass('public/_sources/sass/**/*.scss', { style: 'compressed' })
.pipe(sourcemaps.init())
.pipe(concat('bitage_public.css'))
.pipe(sourcemaps.write('./maps'))
.pipe(gulp.dest('public/_assets/css'))
.pipe(livereload());
});
But still I'm getting Errno::ENOENT: No such file or directory and it lists all the dirs I put into that array.
How do you compile SASS in multiple directories with gulp?
SASS source folder structure:
_sources
layouts
...scss
modules
...scss
vendors
...scss
main.scss
Figured it out!
Well not 100%, still not sure why the multiple path array didn't work.
Anyways so I forgot that in my main web.scss file I already had multiple import statements setup:
#import "vendors/normalize"; // Normalize stylesheet
#import "modules/reset"; // Reset stylesheet
#import "modules/base"; // Load base files
#import "modules/defaults"; // Defaults
#import "modules/inputs"; // Inputs & Selects
#import "modules/buttons"; // Buttons
#import "modules/layout"; // Load Layouts
#import "modules/svg"; // Load SVG
#import "modules/queries"; // Media Queries
So I didn't actually need to try use Gulp the way I was trying, I just needed to target that 1 .scss file directly. So I did that here:
// Compile public SASS
gulp.task('sass', function () {
return sass('public/_sources/sass/bitage_web.scss', { style: 'compressed' })
.pipe(sourcemaps.init())
.pipe(sourcemaps.write('./maps'))
.pipe(gulp.dest('public/_assets/css'))
.pipe(livereload());
});
Now it works because it sees a specific file to target and compile
I was having trouble using '*.scss' too
In the git documentation (https://github.com/sindresorhus/gulp-ruby-sass) they use this sintax:
gulp.task('sass', function(){
return sass('public/_sources/sass/',
{ style: 'compressed'})
.pipe(sourcemaps.init())
});
I tested it and it works, it compiles all the files within the folder.
Just in case someone has the same problem

Resources