Is It possible to dequeue select SCSS #import partial during compilation? - css

Is there a way to remove or disable a SASS #include partial using a preceding variable or dequeue esque method prior to its loading?
I want to use a centralized stock copy of Bootstrap SASS & localized variable override files to build slightly customized CSS files. However, I want to be able to selectively disable unused partials from the stock bootstrap.scss file during the sass build much like using a sass default variable. Is there a way to prevent an #import partial from loading further down in the SASS build chain without editing the stock bootstrap.scss file?

Related

Bundle sass files into single sass file

TL;DR: My question is how to bundle some of my sass files into single sass file?
I've been developing an Angular component library and I package it with ng-packagr. Let's call it #my-lib/ngx-components.
Consumers of my lib will import my components like #my-lib/ngx-components/navbar.
I decided to add theming support to components.
For example, I have a navbar component with default colors (background, text, hover etc.) I want consumers of my library to be able to override these colors with their own theme. That's why I've written a mixin which takes a $theme input and override some css rules as follows (this is a basic version of what I have)
_navbar-theme.sass
#mixin navbar-theme($theme)
$primary-color: map-get($theme, primary-color)
$secondary-color: map-get($theme, secondary-color)
$color: map-get($theme, color)
.navbar
background-color: $primary-color
color: $color
&:hover
background-color: $secondary-color
Each component has its own *-theme.sass file.
I also have global _theming.sass file which imports all of these as follows
_theming.sass
#import './components/navbar/navbar-theme'
#import './components/button/button-theme'
#import './components/dropdown/dropdown-theme'
I want to export this _theming.sass file from my lib, so people can import this file in their own sass file as #import '~#my-lib/ngx-components/theming' and start using all of the mixins available.
If they want to have custom navbar, button etc, they should be able to use those mixins with single import.
I tried to make it look like angular-material theming setup.
At first, I have tried node-sass which is already in my dependencies. But, it tries to build sass into css so it omits mixins in the output file.
Then, I looked at what angular-material has done. They use scss-bundle
I thought "this is exactly what I want." However, it requires scss files, not sass files. It cannot read sass files.
Then, I thought "Okay, I can give up on sass and start using scss. How do I convert all those files to scss without going through them by hand". Then, I found sass-convert. In this question it was said that I can use it within command line. However, when I install sass-convert with npm globally, it didn't give me a command line executable. I think I need Gulp to use it.
I've been avoding to use Gulp from the beginning, because it means another tool to learn and it adds complexity to codebase.
At this point, I feel like "Hal fixing light bulb"
TL;DR: My question is how to bundle some of my sass files into single sass file?
Also, If you can come up with a solution that requires webpack, that's fine too.
Let's through your opinion or questions:
I want to export this _theming.sass file from my lib, so people can
import this file in their own sass file as #import
'~#my-lib/ngx-components/theming' and start using all of the mixins
available. If they want to have custom navbar, button etc, they should
be able to use those mixins with single import.
You need to know, what is your target audience. Mostly people using angular cli for create their app like template scratch.
So you need provide css bundle (people just want import your css) and sass bundle (who want to use your object or your mixin).
I want to export this _theming.sass file from my lib, so people can
import this file in their own sass file as #import
'~#my-lib/ngx-components/theming' and start using all of the mixins
available. If they want to have custom navbar, button etc, they should
be able to use those mixins with single import.
I tried to make it look like angular-material theming setup.
Firstly, you need to know that #angular/material doesn't export sass (they use scss) but they export css thene compiled by scss-bundle (as you mention it) see their code and documentation theme.
I thought "this is exactly what I want." However, it requires scss
files, not sass files. It cannot read sass files.
I would like quote this answer:
Sass is a CSS pre-processor with syntax advancements. Style sheets in
the advanced syntax are processed by the program, and turned into
regular CSS style sheets. However, they do not extend the CSS standard
itself.
It is better you need transfer your code from sass to scss (by yourself), it would not much to do it (I think, I always write scss instead sass file).
Solution:
1. Provide css and sass (scss better)
When you deliver your component libs, You have to provide css and scss. Beacuse angular cli doesn't provide scss loader by default.
Don't use sass file, use scss file see my refer answer on top.
scss-bundle + webpack
Since you have to provide css, you can you webpack shell plugin to bundle scss. Scss have provide cli, if you want to use cli.
2. Structure your scss
Okay, let's take sample from bootstrap#4 module for this case. Bootstrap use structure like this (Documents):
scss
|-- _variables.scss
|-- _mixins.scss
|-- _functions.scss
|-- ...
|-- index.scss
inside index.scss will have like this:
#import 'variables'
#import 'mixins'
#import 'functions'
...
so, this scss you have to deliver beside css. Like bootstrap do, then mixin will available to consumer. Also this good approach when consumer to find scss file in scss folder (easy to pointing which is scss put in).
UPDATE
For bundle to single file you have to create task runner to do it. In your case you want to use webpack, you can create a plugin to do it.
Here example plugin:
scss-bundle-plugin.js
call to you config webpack:
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new SCSSBundlePlugin({
file: path.join(__dirname, 'src/index.scss')
})
],
To try playground, checkout hello-world-loader then:
# install dependency
npm install
# try play ground
npm run webpack
it will create file _theme.scss at ./dist.
My advice don't use webpack, use task runner instead (gulp or grunt) for this simple case. Webpack too advance and hard to write task.
There is also a widely used package, called scss-bundle.
It is quite simple to use, you just create a config file with all relevant configuration and then run scss-bundle.
This for example will use all scss files, imported in entry.scss and move it to out.scss. All imports will be resolved, except for angular themes in this example, like #import '~#angular/material/theming';.
scss-bundle.config.json:
{
"bundlerOptions": {
"entryFile": "my-project/src/entry.scss",
"outFile": "dist/out.scss",
"rootDir": "my-project/src",
"project": "../../",
"ignoreImports": [
"~#angular/.*"
],
"logLevel": "debug"
}
}
My solution for scss / sass files
I've used small module bundle-scss
It bundles files by file name mask. So you need to pass correct mask like ./src/**/*.theme.scss specify destination file and maybe your custom sort-order
You don't have to create one entry point file with all imports. bundle-scss will get all files by mask analyze all imports and include this files as well

Working with Bootstrap 4 and Sass (and Bower)?

I'm learning to use Sass (never used a CSS pre-processor before), and I'm wondering how to use it with Bootstrap 4 properly.
Should I include in my header.php files the bootstrap.min.css? Then when I need to use a Sass mixin or some variable, do I include it in my .scss file?
OR
Should I include all of bootstrap.scss in my styles.scss, then compile it to one style.css and only include that?
You should have a main file (a Sass manifest) where you import your Sass variables, mixins and partials as well as the Bootstrap library. After that's in place Sass will automatically output a CSS file you can include on your header.php file.
Gotchas
Import only the bits you need from Bootstrap (instead of the whole library). Here's a handly list where you can see the components you can choose from.
Make sure to create variables.scss file based on the template Bootstrap provides.
Make sure to import the variables file before the Bootstrap library so it takes effect.
Use Sass in watch mode on development

how to prevent a sass build of each page file when just changing a common scss file

I have a _common.scss file which I import to various page.scss files:
page.scss:
#import "common";
#page {
...
}
_common.scss:
#import "partials/all";
#import "components/all";
...
But the problem is, since all my pages import _common.scss, the way I have things structured, if I make any changes inside _common.scss (or any of the files it imports), sass has to rebuild all the page css files. But if I just make _common.scss its own file and call it with a <link> tag (<link href="common.css">), then the page.scss file has errors, because it is trying to use variables and mixins defined in _common.scss and its imports.
Is it possible to structure my project so that the page.scss files can use all the mixins and variables in _common, but so that sass doesn't have to rebuild each page.css file each time I make a change to the common file? i.e. - make it so that sass only builds the common file when a change is made in common, and only builds the page file when a change is made in page?
I would say it is not possible, since the aim is to have one css for each page at the end. This said it HAS to be rebuild if something is changed in common.

How to use less mixins in meteor with #import and not get multiple definitions

in my current meteor app I have split the less declarations in one file per Controller (iron-router). I have a common file - where I have defined some mixins - which is imported in each less file. My problem is that the classes are imported multiple times in each route.
The file structure is:
mixins.import.less (new names, reference http://docs.meteor.com/#less)
.grid-container {
// something
}
postList.less
#import (once) url('/client/views/mixins.import.less');
postDetail.less
#import (once) url('/client/views/mixins.import.less');
Then in the Chrome inspector I found duplicated everything I have written in mixins.import.less. Is it possible to avoid this double import?
Assuming you want the mixin code at least once in your compiled css (perhaps not, some just want them as mixins, not classes in the css code), then make sure you set it to bring in the "mixins.import.less" file all by itself. Then for all your dependent files using it, do this:
"postList.less", "postDetail.less", etc.
#import (reference) url('/client/views/mixins.import.less');
The (reference) option has been available since LESS 1.5, and will only bring in the code for reference purposes to be used in the LESS file, but will not itself output any css.
Meteor bundles css and js/html resources all together as a single css and a single js file in production.
In development, they are individually served, but still at the same time, during initial page load (first ever request to server)
For less files, a css file is created for each (during development). Since you are importing, what Meteor basically does is create each corresponding css file that each contain the import individually.
And when they are served to the client all together (take a look at the head section of the generated html), you end up with that many copies of the imported style declarations.
Therefore, due to this bundling behaviour of Meteor, you can just keep one copy of your less mixins in a less file, and not import at all, since they are going to be served to the client in CSS form anyway.
Also, it is possible to trick Meteor into bypassing as described in the unofficial meteor faq:
... you can change the extension of the less files to be imported from .less to .lessimport and then change your #import file.less to #import file.lessimport. This will prevent the less compiler from automatically trying to compile all your import files independently, yet still let you use them ...

LESS CSS Hierarchical Heritance

In a project I have separated the CSS into two sub-projects:
C:/Projects/_Framework/css
C:/Projects/_Base/css
Note: I've purposely prefixed the above with the C:/Projects/ to illustrate that they are totally separate projects from each other.
The _Framework has basic things like reset, typography, forms, and a grid.
The _Base has the default theme for the project. _Base imports the _Framework
Inside _Base I have files like header.less and variables.less which store the design of the header and the colours for the theme.
So if I have my project at: C:/Projects/App
And inside this App project, I have a master CSS file that looks like:
#import "/_Framework/_loadAll.less
#import "/_Base/_loadAll.less
Which imports both the Framework and the Base theme (the reason that Base doesn't load the Framework itself is for flexibility but has scope to be done this way instead if needed).
The plan is to make it so that if a header.less file existed inside _App then it would automatically override the import of the one in _Base.
How could this be achieved?
You can't exclude a whole .less file by checking for duplicate names. Just make sure that the header.lessfile of your _App project is imported after the one from _Base.
Pseudo code:
#import "/_Framework/_loadAll.less
#import "/_Base/_loadAll.less
#import "_App/header.less"
And overwrite any properties you need in the _App/header.less file.
If you need to overwrite everything in the _Base/header.less file, I would suggest it's not a good fit for a Base style.

Resources