How to organize sass files, so compass includes them in the right order - compass-sass

I'm building a single page app using the most recent yeoman build 1.0.0beta3 and compass 0.12.2
When starting compass:server I get lots of errors, but during dev time all seems to be ok in my browser. grunt build then does not fail, but builds improper CSS output, so that the layout in the browser is borken. Maybe that's all my fault, caused by a misunderstanding.
What I have is a main.sass file with all my includes:
// compass
#import 'compass'
#import 'compass/reset'
#import 'compass/css3'
... and so on
//custom includes in the right order
#import 'base/dimensions'
#import 'base/colors'
#import 'base/layout'
The file base/dimensions now defines:
// height of the footer
$footer-height: 50px
And (later) in base/layout I make use of that:
.content-bg
background-color: rgba(0, 0, 0, 0.05)
bottom: $footer-height
... and more
When starting the grunt and compass server now, I get the following error:
Running "compass:server" (compass) task
directory .tmp/styles/
create .tmp/styles/avendor_font-awesome.css
create .tmp/styles/base_colors.css
create .tmp/styles/base_dimensions.css
error app/styles/base_layout.sass (Line 23: Undefined variable: "$footer-height".)
And lots of similar errors. (The footer height is indeed ok during dev time.)
I do not know how to solve that problem, and I do not know either if this causes the improper CSS after a build run. But when I build by issuing grunt I see the same errors in the console.
I should mention, I made some changes to Gruntfile.js, so that .sass files are loaded from subdirectories of /styles also:
grunt.initConfig({
yeoman: yeomanConfig,
watch: {
coffee: {
files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
tasks: ['coffee:dist']
},
coffeeTest: {
files: ['test/spec/{,*/}*.coffee'],
tasks: ['coffee:test']
},
compass: {
**files: ['<%= yeoman.app %>/styles/{,**/}*.{scss,sass}'],**
tasks: ['compass']
},
livereload: {
files: [
'<%= yeoman.app %>/*.html',
'{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
**'{.tmp,<%= yeoman.app %>}/styles/{,**/}*.css',**
'{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,webp}'
],
tasks: ['livereload']
}
},
Can anyone enlighten me?
Regards
Felix

For everyone facing the same problem: The naming of the files does the trick. Every file that is to be included in you main.css like so:
#include 'base/colors'
has to be named:
_colors.sass
instead of:
colors.sass
in the base directory in that case. What I did as well, was renaming main.css to main.css.sass
Now everything works correctly and I learned another thing the hard way.

Related

Grunt file not building CSS file (SASS): Errno::ENOENT: No such file or directory # rb_sysopen - undefined

I have a Grunt file, that should build my CSS file. When I run the task in the Task Runner (Visual Studio), I get below error:
Running "sass:dist" (sass) task Errno::ENOENT: No such file or
directory # rb_sysopen - undefined Use --trace for backtrace.
Warning: Exited with error code 1 Use --force to continue. Aborted
due to warnings. Process terminated with code 6.
My Grunt file:
module.exports = function (grunt) {
grunt.initConfig({
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'/css/styles.css': '/css/sass/styles.scss'
}
}
},
watch: {
css: {
files: ['css/sass/*.scss'],
tasks: ['sass'],
options: {
livereload: true,
},
},
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['watch']);
};
My directory:
I use Visual Studio 2017 and have a standard ASP.NET Core project.
I read a bit, and it seems it could be the SASS cache. However, when I run the rm .sass-cache/ -R command, I get
rm: cannot remove '.sass-cache/': No such file or directory
Any ideas?
My guess is that there's confusion over what path you're starting from. I believe grunt runs from the project root, and wwwroot is a subfolder of that. Either prefix your paths in the grunt file with wwwroot/, or consider moving your .scss files out of wwwroot entirely, since they aren't intended to be served. They can go under the project root, and you can have grunt copy the .css outputs into wwwroot where they belong.

Laravel 5.4 - Bootstrap glyphicons don't work after sass integration

Well, I just installed fresh Laravel 5.4. Then installed npm and decided first time to use webpack instead of gulp.js. As you know, Laravel default provides sass Bootstrap integration. Used this command to generate my css from sass.
npm run dev
Bootstrap, Jquery worked perfect, but Glyphicons weren't displayed. Checking my public/css/app.css I saw, that Glyphicons font-face path are not suitable.
src: url(/fonts/glyphicons-halflings-regular.eot?f4769f9bdb7466be65088239c12046d1);
If I, manually use ../fonts instead of /fonts it will work. I tried to figure out and edit the default path. In _variables.css I set:
$icon-font-path = "../fonts" - but npm gives error.
By default it is: "~bootstrap-sass/assets/fonts/bootstrap/"
Copied fonts folder inside puclic/css folder, didn't work.
Added options to the webpack.mix.js file:
options({processCssUrls: false})
and in _variables.css again set:
$icon-font-path = "../fonts"
Run npm-run-dev and it worked, glyphicons were displayed. But, I don't want to set false for processCssUrls. Because, in this case I will not able to minimize css files using command: npm run production.
Also, I followed this question, but couldn't find any answer, all solutions didn't work.
glyphicons not showing with sass bootstrap integration
Finally, found the solution. In webpack.config.js set:
publicPath: '../'
instead of Mix.resourceRoot
{
test: /\.(woff2?|ttf|eot|svg|otf)$/,
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]?[hash]',
publicPath: Mix.resourceRoot
}
},

stylesheet import error in build system

I don't know why but this irregularity always happens in my Yeoman build system. In my Gulpfile.js, the directory where all .scss files will be watched is in app/styles/**/*.scss. The strategy I used is: the only compiled stylesheet that I would link to HTML file is the main.scss, where the other .scss files are already imported to. So when the compilation is done, only the main.css will be linked.
main.scss
#import 'base';
#import '_banner';
#import '_works';
#import '_design';
#import '_story';
#import '_contact';
Here is the image of the content of the folder where the stylesheets are located:
The problem is, every time I make changes to one of any of my .scss files, it throws an error that refers to importing error; but when I try to make some changes again, the compilation is successful.
In my Gulpfile.js:
gulp.task('styles', () => {
return gulp.src('app/styles/main.scss')
.pipe($.plumber())
.pipe($.if(dev, $.sourcemaps.init()))
.pipe($.sass.sync({
outputStyle: 'compressed',
precision: 10,
includePaths: ['.']
}).on('error', $.sass.logError))
.pipe($.autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))
.pipe($.if(dev, $.sourcemaps.write()))
.pipe(gulp.dest('.tmp/styles'))
.pipe(reload({stream: true}));
});
Is this some kind of a bug? What should I do to prevent this from happening again?

How to #import external SCSS properly with webpack and Vue.js?

As in Material Component Web's example, I want to be able to import SCSS from my node_modules like this:
#import '#material/elevation/mdc-elevation';
However, I'm getting this error message when trying to run the webpack build:
File to import not found or unreadable: #material/elevation/mdc-elevation.
#import './~/#material/elevation/mdc-elevation.scss'; doesn't work either.
I'm pretty sure the issue is somewhere in my webpack config, but I can't figure out where.
What did they do in Material Components Web's Vue.js example in order to make it work?
Here's my npm-debug.log in case you need it.
And here's the corresponding Git repository: sk22/spg-tinf-sem03/proj01
Thanks in advance!
Edit: I want to be able to import the scss files, not the compiled css.
Got it.
here's a part of my webpack 2 config's module.rules:
{
test: /\.(sass|scss)$/,
use: [
'style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
includePaths: [path.resolve(__dirname, 'node_modules')],
},
},
],
},
So what did I do wrong?
My options object was placed in the rule directly, not the loader.
The old webpack config rule looked like this:
{
test: /\.(sass|scss)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
options: { includePaths: [path.resolve(__dirname, './node_modules')] },
},
See the difference? Instead of the 'sass-loader' string, I extended it to an object, containing the loader name and the options object, because the options only apply to the sass-loader.
(You could also drop the path.resolve and only write 'node_modules', but it might be safer to leave it.)
Check out this documentation page for further information. https://webpack.js.org/configuration/module/#rule-use
Without that loader, you must prefix each import with a ~, which webpack converts to the node_modules folder, at least with my previous configuration.
But this will break 3rd party SCSS frameworks like Material Components Web, because they use #import statements without a leading ~ themselves, for example here.
Inside .vue files
This will not work in .vue files, as vue-loader just uses sass-loader without any options by default.
So if you want that to work, you probably need to make use of vue-loader's own options, as described in its documentation.
(I'm unable to get it to work for some reason I don't know...)
EDIT: Webpack has a section on sass-loader now: https://webpack.js.org/loaders/sass-loader/ also mentioning includepaths.
I had the same issue with #material and Vue. I managed to resolve the problem without adjusting the use property directly.
Solution
Step 1: First create a default Vue 2.1 project using the CLI.
Your file structure will have a ./build directory.
Step 2: Open the file 'utils' you will see a cssLoaders() function which returns an object/map for the languages vue-loader supports.
You will see both sass and scss in that map.
Step 3: Change the values of sass and scss to:
sass: generateLoaders('sass', {
indentedSyntax: true,
includePaths: [path.resolve(__dirname, '../node_modules')]
}),
scss: generateLoaders('sass', {
includePaths: [path.resolve(__dirname, '../node_modules')]
}),
Step 4: Go to the .vue file you're using and change the lang attribute in your <style> element to either sass or scss.
Step 5: After you've done that go to the terminal/console and install sass-loader with:
npm install sass-loader node-sass webpack --save-dev
Step 6: Then run npm run dev and it should work.
Why does this work?
Libraries
I dug around a bit and it turns out sass-loader uses node-sass which has some options such asincludePaths one mentioned by #22samuelk. IncludePaths tells node-sass or rather the underlying library LibSass to include sass files from that directory/path.
Vue
Sass-loader options
By default Vue expects your assets to be in your projects src/assets folder (correct me if I'm wrong). You can however use ~ to indicat you want to start at your projects root which would look like `~/node_modules/#material/smth/mdc-smth.scss.
Now if you want your sass-loader to use something other than those options you need to explicitly tell them.
Hence path.resolve(__dirname, '../node_modules' since the utils file is in ./build and you need to use an absolute path for sass-loader to understand where to look.
Vue-loader config
This is not really specific to the question but the vue-loader config defined in vue-loader.conf.js works as follows:
It uses the map returned by cssLoaders() to build the loaders expected by webpack.
The returned map ({key:value}) is then used by providing key as a file extension used in test: for a loader object. The value is used as the loader object.
Which would like like this:
{
test: /\.(key)$/,
use: [
{
loader: '//ld//-loader',
options: {
/*Options passed to generateLoaders('//ld//', options)*/
},
},
],
}
Where key is the file extention. In this case that would be either sass or scss. And //ld//is the loader you which to use. Which is shown in Step 3 as 'sass'.
Hopefully this clears up some stuff. Took me a while because I just started using Vue.

webpack scss background image path error

I have the following rule on line 258 of my style.scss file:
background: url(img/bg-light-grey.gif)
I then run the command webpack and it successfully builds. I go to my webpage but I see I don't see the image included on my webpage. I open up chrome debugger and it says that line 258 of my style.scss has:
background: url(build/4932049asdfjaoi3j234.gif)
In my Chrome debugger, I replace that line with absolute url
background: url(http://localhost:8080/experiment/build/4932049asdfjaoi3j234.gif)
And now the image appears.
How do I get webpack to compile the file paths properly for my images? Alternatively, I don't mind stringify or base64encode these things into my bundle.js file. Whatever it takes to get these images to render properly.
I found the answer here:
Webpack - background images not loading
I had to make a change in my webpack.config.js from
{ test: /\.scss$/, loaders: [ 'style', 'css?sourceMap', 'sass?sourceMap' ]},
to
{ test: /\.scss$/, loaders: [ 'style', 'css', 'sass' ]},

Resources