LESS - similar function to Compass "add_import_path" - gruntjs

Coming from a Compass/Sass background. Working on a Bootstrap/KendoUI Less project that's compiling with Grunt.
In Compass, a config option exists for "add_import"path" http://compass-style.org/help/documentation/configuration-reference/
What it allows you to do is set a hierarchy for SASS compilation based on file structure. So if I had a base SASS workflow/files structure that looked like this:
../
/default
style.scss
header.scss
/child
header.scss
And I had set /child as the primary directory and /default as an import path, it would compile the SASS in /child and extract from /defaultonly what wasn't in /child. Essentially, it's a way to override files instead of editing core files.
I'm looking to replicate this process through a grunt module to avoid altering core bootstrap or kendoUI files while being able to still override them if necessary, without !important tags or other ugly solutions.

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

Compiling Sass (scss) to css

I have this template - web template - editorial when I added it to my existing Meteor app it does not load the scss files, only the css file which is in the client directory. Though I put the scss files in the public folder. What best way can I add this? because I could not get it to work i decided to compile the scss to css.
sass_folder
scss_subfolder
----base_scss_subfoler
_partial1.scss
_partial2.scss
----components_scss_subfoler
_buttons.scss
_textbox.scss
----layouts_scss_subfoler
_pages.scss
_footer.scss
----libs_scss_subfoler
_functions
_vars
_skels
_mixins
main.scss
ie8.scss
ie9.scss
css_output_folder
I have tried to compile the files by doing thus on the cmd: sass --update scss:css it only compiled the main.scss, ie8.scss, ie9.scss to the css folder, other are not compiled. How do I compile all at once and maintain the same sub-directory folder in the css folder. Why and how do I do this?
If other files name start with _ character then these files are partials meaning they get no compiled and their content can only used with import.
Read the official doc about partials.
The files with names starting with underscore are considered as partials and not compiled to css files. That is why you are not seeing those in your output css.
Please navigate to section with heading 'Partials' in this document ... and read the next 2 sections.
You can create partial Sass files that contain little snippets of CSS that you can include in other Sass files. This is a great way to modularize your CSS and help keep things easier to maintain. A partial is simply a Sass file named with a leading underscore. You might name it something like _partial.scss. The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file. Sass partials are used with the #import directive.

Both SCSS and CSS files in plugin directory?

Forgive me if this is naive, but I am used to using just CSS. Sass seems pretty cool and I'm down to learn it, but for some reason many of the Javascript or jQuery plugins I'm downloading have both a CSS and SCSS file associated with the stylesheet. I don't want to have to be editing two files to get results on the page, why would both be there when they seem like copies except for a few key areas? See image below, seems like there is an extra CSS file per SCSS. Is that because some browsers cannot compile the SCSS?
CSS and SCSS in same directory
Is that because some browsers cannot compile the SCSS?
Yes. There is a command line utility which converts the .scss to .css. Probably the .map file is a reverse-conversion aid for browser inspectors that understand it.
Whenever I have generated files (like a .min.js, or in your case .css that came from a .scss), I make sure the appropriate command-line conversion tool is executed automatically as part of my build script.
I'm not sure what kind of build system you are using, but there is some command line tool for conversion that will need to be executed.
You are not expected to manually update both formats. SCSS to CSS command-line converters existed long before any browser (is there one yet?) started to support SCSS.
No browser (at least major) is able to directly use SASS (or LESS). You always need to compile scss files to css, before you could use them.
You can compile css by build tools like grunt or gulp. You can even configure it to watch updates in scss files and recompile css if anything was changed.
You could have following types of files after build:
style.scss <- this is source file
style.css <- this is css file created from SASS file
style.min.css <- this is css file minified
style.css.map <- this is source map of scss file
Here you can read why css files are minified. Here you can read what are source maps for.

Compile css and sass files to single css file using gruntjs

I have a bootstrap.css file which I want to compile with my custom styles from style.sass into single output file, for example - style.css.
For sass compilation I use gruntjs with grunt-contrib-sass extension. My Gruntfile.js config for sass looks like this:
sass: {
dist: {
options: {
//style: 'compressed',
style: 'expanded',
lineNumbers: true
},
files: {
'build/styles/style.css': 'src/styles/style.sass'
}
}
}
I've tried to import bootstrap.css into sass file, but instead it only generates next code in output css (which is correct behavior http://sass-lang.com/documentation/file.SASS_REFERENCE.html#import):
#import url(bootstrap.css);
.....
/*my style.sass rules*/
I even tried to list multiple files in order of concatination and processing, like in uglifier settings:
files: {
'build/styles/style.css': ['src/styles/bootstrap.css', 'src/styles/style.sass']
}
But this only adds bootstrap.css into final style.css file ignoring style.sass existence.
As I'm new in gruntjs, I can't figure out how this should be done properly.
The Grunt configuration is correct. The reason your file is not being imported is because of the way SASS is designed to work.
The SASS documentation states:
By default, it looks for a Sass file to import directly, but there are a few circumstances under which it will compile to a CSS #import rule:
If the file’s extension is .css.
If the filename begins with http://.
If the filename is a url().
If the #import has any media queries.
Since the file you are importing has a .css extension it will therefore not be imported directly but remain a standard CSS #import.
You have three options to resolve this:
Rename the included file to _bootstrap.scss. (If you don't add the underscore a bootstrap.css will be created along with your main output file which is unnecessary.)
Include the Bootstrap SCSS source as a dependency of your project and build against that. Install the Bootstrap source using Bower by typing $ bower install bootstrap-sass-official in your project root folder. (For instructions on setting up Bower see the Bower website.) Then you can replace your import above with #import 'bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap';.
Use a concatenation library such as grunt-contrib-concat to combine Bootstrap.css and your main style sheet during your build process.
This first option is fine if you downloaded the bootstrap CSS file into your project manually, however, if you are including it as a dependency with npm/bower it is not ideal.
I would recommend the second option since building Bootstrap from source will not only solve your problem but allow for customization of Bootstrap variables to fit your theme rather than overwriting them with subsequent style rules as well. The only downside is that your build process might be slightly longer due to the rather large SASS build of the Bootstrap source.

Raw CSS stylesheet with sass

I am building a set of Sass stylesheets using Compass.
I also have a minified copy of bootstrap.css that I would like to include in my deployed site. However, I'm not sure where to keep it or what to do with it.
If I rename it to bootstrap.scss then Compass will pick it up and compile it. This takes a few seconds and I really don't need to add to the build time.
If I leave it named as bootstrap.css then it gets ignored.
Ideally there would be a flag, or some way of telling compass to simply copy that file across rather than attempt to compile it. Does that exist?
If your CSS file should not be compiled into your finished CSS file, then it should be placed wherever your compiled CSS files go. However, this is generally not the desired behavior: a vanilla CSS #import generates extra HTTP requests.
There isn't really a down side to having your CSS file compiled by Sass, as the compilation of that file should be cached (unless you're deleting your .sass-cache files?). Sass should only recompile a file if it or something it depends on changes.

Resources