I have a project structure where each component has its own SCSS file, and I would like to have all of these automatically imported into the project's main app.scss file, without having to list them all individually or update the list every time a new component is added. I know that merging a bunch of globbed CSS files could cause issues with selector order, but that is not a concern here.
I have tried this, with the components.scss file imported into app.scss:
mix.styles('resources/views/components/*.scss', 'resources/css/components.scss');
mix.sass('resources/css/app.scss', 'public/css');
And it basically works.
Except, mix.styles() runs after the Sass compilation, so you end up with the components.scss file from the previous execution being imported, rather than the current one.
Is there a way to solve this? Or is there another approach that would work?
As Sass #import does not support glob paths it's not possible to do something like this in app.scss as far as I am aware:
#import 'resources/views/components/*';
Discovered this can be done quite easily with node-sass-glob-importer, which is compatible with the Dart Sass implementation that Mix uses:
const sassGlobImporter = require('node-sass-glob-importer');
mix.sass('resources/css/app.scss', 'public/css', {
sassOptions: {
importer: sassGlobImporter(),
}
});
resources/css/app.scss
#import '../views/components/**/*.scss';
I'm using Sage, a WordPress framework, and it lets you choose during creation some css frameworks, but I want to use Materialize CSS instead.
It uses Webpack to build and combine the .scss files into one. I did an npm install materialize-css so it's in my node_modules. In my project structure, I made an scss file that's used to import the module basically.
I also have bulma in this build, included via the original creation, so I can try to see how the structure is setup. It uses the following import statement:
#import "~bulma";
This works. I'm so confused about how this works. I think the ~ (tilde) tells Webpack something, but I don't know what. What I figured is that Webpacks checks the package.json file or something and finds it in the node_modules.
I've tried #import "~materialize-css"; with no luck.
Can someone explain what the heck Webpack is doing? Haha, because I can't find any documentation on this.
Here are the node_module folder structures, maybe this has something to do with it:
Perhaps the root of Bulma is bulma.sass yet for Materialize-CSS, there's no file, it's in sass/materialize.scss.
If needed, here's the github for the Sage framework, the webpack.config.js is in the build folder: https://github.com/roots/sage/tree/master/resources/assets
You have to specific the file you want to import also like this
#import "~bootstrap/scss/bootstrap";
#import "~font-awesome/scss/font-awesome";
#import "~toastr/toastr";
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
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.
Is there anyway to import a regular CSS file with Sass's #import command? While I'm not using all of the SCSS syntax from sass, I do still enjoy it's combining/compressing features, and would like to be able to use it without renaming all of my files to *.scss
After having the same issue, I got confused with all the answers here and the comments over the repository of sass in github.
I just want to point out that as December 2014, this issue has been resolved. It is now possible to import css files directly into your sass file. The following PR in github solves the issue.
The syntax is the same as now - #import "your/path/to/the/file", without an extension after the file name. This will import your file directly. If you append *.css at the end, it will translate into the css rule #import url(...).
In case you are using some of the "fancy" new module bundlers such as webpack, you will probably need to use use ~ in the beginning of the path. So, if you want to import the following path node_modules/bootstrap/src/core.scss you would write something like #import "~bootstrap/src/core".
NOTE:
It appears this isn't working for everybody. If your interpreter is based on libsass it should be working fine (checkout this). I've tested using #import on node-sass and it's working fine. Unfortunately this works and doesn't work on some ruby instances.
This was implemented and merged starting from version 3.2 (pull #754 merged on 2 Jan 2015 for libsass, issues originaly were defined here: sass#193 #556, libsass#318).
To cut the long story short, the syntax in next:
to import (include) the raw CSS-file the syntax is **without `.css`** extension at the end (results in actual read of partial `s[ac]ss|css` and include of it inline to SCSS/SASS):
#import "path/to/file";
to import the CSS-file in a traditional way syntax goes in traditional way, **with `.css` extension** at the end (results to `#import url("path/to/file.css");` in your compiled CSS):
#import "path/to/file.css";
And it is damn good: this syntax is elegant and laconic, plus backward compatible! It works excellently with libsass and node-sass.
__
To avoid further speculations in comments, writing this explicitly: Ruby based Sass still has this feature unimplemented after 7 years of discussions. By the time of writing this answer, it's promised that in 4.0 there will be a simple way to accomplish this, probably with the help of #use. It seems there will be an implementation very soon, the new "planned" "Proposal Accepted" tag was assigned for the issue #556 and the new #use feature.
UPD: on 26 October 2020 lib-sass was deprecated, therefore issue #556 was immediately closed.
__
answer might be updated, as soon as something changes.
Looks like this is unimplemented, as of the time of this writing:
https://github.com/sass/sass/issues/193
For libsass (C/C++ implementation), import works for *.css the same way as for *.scss files - just omit the extension:
#import "path/to/file";
This will import path/to/file.css.
See this answer for further details.
See this answer for Ruby implementation (sass gem)
You must prepend an underscore to the css file to be included, and switch its extension to scss (ex: _yourfile.scss). Then you just have to call it this way:
#import "yourfile";
And it will include the contents of the file, instead of using the CSS standard #import directive.
Good news everyone, Chris Eppstein created a compass plugin with inline css import functionality:
https://github.com/chriseppstein/sass-css-importer
Now, importing a CSS file is as easy as:
#import "CSS:library/some_css_file"
If you have a .css file which you don't wish to modify, neither change its extension to .scss (e.g. this file is from a forked project you don't maintain), you can always create a symlink and then import it into your .scss.
Creates a symlink:
ln -s path/to/css/file.css path/to/sass/files/_file.scss
Imports symlink file into a target .scss:
#import "path/to/sass/files/file";
Your target output .css file is going to hold contents from imported symlink .scss file, not a CSS import rule (mentioned by #yaz with highest comment votes). And you don't have duplicated files with different extensions, what means any update made inside initial .css file immediately gets imported into your target output.
Symbolic link (also symlink or soft link) is a special type of file
that contains a reference to another file in the form of an absolute
or relative path and that affects pathname resolution.
– http://en.wikipedia.org/wiki/Symbolic_link
You can use a third-party importer to customise #import semantics.
node-sass-import-once, which works with node-sass (for Node.js) can inline import CSS files.
Example of direct usage:
var sass = require('node-sass');,
importOnce = require('node-sass-import-once');
sass.render({
file: "input.scss",
importer: importOnce,
importOnce: {
css: true,
}
});
Example grunt-sass config:
var importOnce = require("node-sass-import-once");
grunt.loadNpmTasks("grunt-sass");
grunt.initConfig({
sass: {
options: {
sourceMap: true,
importer: importOnce
},
dev: {
files: {
"dist/style.css": "scss/**/*.scss"
}
}
});
Note that node-sass-import-once cannot currently import Sass partials without an explicit leading underscore. For example with the file partials/_partial.scss:
#import partials/_partial.scss succeeds
#import * partials/partial.scss fails
In general, be aware that a custom importer could change any import semantics. Read the docs before you start using it.
If I am correct css is compatible with scss so you can change the extension of a css to scss and it should continue to work. Once you change the extension you can import it and it will be included in the file.
If you don't do that sass will use the css #import which is something you don't want.
I figured out an elegant, Rails-like way to do it. First, rename your .scss file to .scss.erb, then use syntax like this (example for highlight_js-rails4 gem CSS asset):
#import "<%= asset_path("highlight_js/github") %>";
Why you can't host the file directly via SCSS:
Doing an #import in SCSS works fine for CSS files as long as you explicitly use the full path one way or another. In development mode, rails s serves assets without compiling them, so a path like this works...
#import "highlight_js/github.css";
...because the hosted path is literally /assets/highlight_js/github.css. If you right-click on the page and "view source", then click on the link for the stylesheet with the above #import, you'll see a line in there that looks like:
#import url(highlight_js/github.css);
The SCSS engine translates "highlight_js/github.css" to url(highlight_js/github.css). This will work swimmingly until you decide to try running it in production where assets are precompiled have a hash injected into the file name. The SCSS file will still resolve to a static /assets/highlight_js/github.css that was not precompiled and doesn't exist in production.
How this solution works:
Firstly, by moving the .scss file to .scss.erb, we have effectively turned the SCSS into a template for Rails. Now, whenever we use <%= ... %> template tags, the Rails template processor will replace these snippets with the output of the code (just like any other template).
Stating asset_path("highlight_js/github") in the .scss.erb file does two things:
Triggers the rake assets:precompile task to precompile the appropriate CSS file.
Generates a URL that appropriately reflects the asset regardless of the Rails environment.
This also means that the SCSS engine isn't even parsing the CSS file; it's just hosting a link to it! So there's no hokey monkey patches or gross workarounds. We're serving a CSS asset via SCSS as intended, and using a URL to said CSS asset as Rails intended. Sweet!
To import a regular CSS file into Sass:
Official Sass Documentation: Import CSS into Sass
Simple workaround:
All, or nearly all css file can be also interpreted as if it would be scss. It also enables to import them inside a block. Rename the css to scss, and import it so.
In my actual configuration I do the following:
First I copy the .css file into a temporary one, this time with .scss extension. Grunt example config:
copy: {
dev: {
files: [
{
src: "node_modules/some_module/some_precompiled.css",
dest: "target/resources/some_module_styles.scss"
}
]
}
}
Then you can import the .scss file from your parent scss (in my example, it is even imported into a block):
my-selector {
#import "target/resources/some_module_styles.scss";
...other rules...
}
Note: this could be dangerous, because it will effectively result that the css will be parsed multiple times. Check your original css for that it contains any scss-interpretable artifact (it is improbable, but if it happen, the result will be hard to debug and dangerous).
to Import css file in to scss simply use the this:
#import "src/your_file_path";
without using extension .css at the end
It is now possible using:
#import 'CSS:directory/filename.css';
I can confirm this works:
class CSSImporter < Sass::Importers::Filesystem
def extensions
super.merge('css' => :scss)
end
end
view_context = ActionView::Base.new
css = Sass::Engine.new(
template,
syntax: :scss,
cache: false,
load_paths: Rails.application.assets.paths,
read_cache: false,
filesystem_importer: CSSImporter # Relevant option,
sprockets: {
context: view_context,
environment: Rails.application.assets
}
).render
Credit to Chriss Epstein:
https://github.com/sass/sass/issues/193
Simple.
#import "path/to/file.css";