Rails application.css.scss not aware of other scss files in use? - css

I'm following M Hartl's Rails Tutorial, and trying to add a bootswatch theme.
I have succeeded by using the boostrap-sass gem as defined in the tutorial, and twitter-bootswatch-rails gem from the net.
However, in Hartl's tutorial, all the CSS that we write in addition to default bootstrap is in a separate custom.css.scss file.
My application.css.scss file (Renamed from Rails default .css) contains
#import "bootstrap-sprockets";
// Import cerulean variables
#import "bootswatch/cerulean/variables";
// Then bootstrap itself
#import "bootstrap";
// And finally bootswatch style itself
#import "bootswatch/cerulean/bootswatch";
#import "custom";
Which works, however the custom.css.scss file has a reference to $gray-light, a variable set in bootstrap. The server will return an error at the variable reference in the css file, unless I add
#import "boostrap-sprockets";
#import "bootstrap";
to custom.css.
End result though, is I now have two gigantic CSS files being used, for what I would think is no reason.
I thought the idea of
#import "custom";
was to include my custom.css.scss file into the application.css.scss file so that it would all be in one place, and variables would work nicely.
The other method that works is to dump my entire custom.css.scss contents into application.css.scss but that defeats the point of having separate files.
Am I doing something wrong?
Edit: To add more fuel to the fire, I deleted the two lines from custom.css, and instead `#import bootswatch/cerulean/variables"; and it works. However, the resulting CSS that's on the website itself has NOTHING from that file.

This could well be wrong, but I post an answer to my own question as follows:
It appears that the sprockets lines //= require_self and //= require_tree, even when listed inside the comment section of the manifest as they are by default, are actually running.
This then causes each of the files "required" to be compiled separately. As a result, instead of getting a single application-FINGERPRINT.css file, I was getting an application, a custom, and a static_pages one. I assume this is the "require_tree" line.
After removing these lines, the #import "custom"; line works as I expected it to. The files are all combined into an application-FINGERPRINT.css file and I no longer need to #import anything at the top of custom.scss.

Related

Wordpress: import scss from plugin in my theme

I'm working on a theme and plugin that share components. In my theme I have a scss file and in this I want to import a main.scss file from my plugin. This is the situation:
Plugin main.scss
#import "slick";
#import "slick_theme";
#import "~bootstrap/scss/bootstrap";
#import "~aos/dist/aos.css";
#import "../../../my-directory/**/*.scss";
Theme main.scss
#import "../../plugins/my-plugin/assets/src/scss/main";
II can't compile the main.scss of my theme because it can't resolve the url of node_modules and the directory with wildcards.
Any ideas?
(A) Easiest (and fastest!) way: Use full relative path!
As SASS don't support the wild cards in SASS files using #-rules: just remove wild cards and write full relative path to node-modules like #import '../../complete/relative/path/to/node/module/dir/file.scss' ;-)
(B) ALTERNATIVE: Set includePath
Set node directory as includePath for your project. As I don't know the compiler you use here are the information how to do in original SASS (but 'includePath' variable is almost the same):
https://sass-lang.com/documentation/js-api#includepaths
In that case you are able to #import only by using the filename.
Additional notes:
In SASS rule #import does NOT support mulitple includes at all. Means: in a SASS file #import '*.scss' (as you try in your example by using wildcard * in filename) will not work at all. You ALLWAYS need to specify a concrete single file: #import 'concreteFile.scss'.
In SASS you can remove the suffix .scss from filenames. As this #import path/to/filename'` works as well.

Organize application SASS files using Bootstrap

I'm starting to work on a large application styling files. As Bootstrap 4 offers SASS files, I decided to follow that path.
I have built the following files structure:
theme.scss: general definitios for the theme like colors and fonts. Today there is just one but there could be more in the future.
global.scss: includes Bootstrap, some Bootstrap overrides and application componentes -i.e. a field with its label as part of the top border.
site.scss: general application styles.
additional page-specific SCSS files. I.e.: login.scss.
The problem I'm having is that global.scss -the one that imports Bootstrap- is then imported by site.scss as well as other files like page-specific SCSS files. So, Bootstrap styles end up in more than one compiled CSS. Compiled CSS files are what the application actually references.
I've previously used LESS and I could solve this using #import (reference) "bootstrap" instead of just plain #import "bootstrap". With SASS I haven't been able to find any solution to this problem without modifying Bootstrap core files.
Is there any other recommended way to organize the files and avoid this problem? Am I missing something or doing anything wrong?
Here are the files contents (they are large files but I'm posting only enough contents to show the problem I'm having):
theme.scss
$my-primary-color: #04459a;
global.scss
#import "../theme.scss";
$primary: $my-primary-color;
#import "../../third-party/bootstrap/scss/bootstrap.scss";
%field{
// [...]
}
site.scss
#import "global.scss";
div.field {
#extend %field;
}
// [...]
login.scss (or many other)
#import "global.scss";
// [...]
In the application I'm referencing site.css and login.css (in the loign page, of course) and both of them include Bootstrap styles.
I've built something that works for me, not sure if it's the best solution or which drawbacks it has, though.
I took some ideas from this article: My favored SCSS setup with Bootstrap 4. Here's what I've built:
First I created two SASS files for importing Bootstrap (similar to what the article does with bootstrap/_config.scss but splitted):
bootstrap/_sass-componentes.scss
#import "../../terceros/bootstrap/scss/_functions.scss";
#import "../../terceros/bootstrap/scss/_variables";
#import "../../terceros/bootstrap/scss/_mixins";
bootstrap/_config.scss
#import "_sass-componentes.scss";
// Every other bootstrap file I want to include:
#import "../../terceros/bootstrap/scss/_root";
#import "../../terceros/bootstrap/scss/_reboot";
#import "../../terceros/bootstrap/scss/_type";
// [...]
#import "../../terceros/bootstrap/scss/_utilities";
#import "../../terceros/bootstrap/scss/_print";
Then in global.scss I changed the bootstrap.scss import line to import only bootstrap/_sass-componentes.scss
Finally, in site.scss I included global.scss (such as it was before) and then full Bootstrap files trough bootstrap/_config.scss. **
** After importing _config.scss I also import my Bootstrap customizations. For doing them I followed the recomendation of the linked article although they do not apply directly to my own question.

Java FX CSS #import path issue

In Java8_31 I imported different CSS files like that in my main.css:
#import "style/common/test1.css";
#import "style/common/test2.css";
All files were in the package style/common and it worked great.
Now with the build Java8_40 I did the same thing, but I get the following error message:
Could not find stylesheet:
file:/mypath/../style/common/style/common/test2.css
com.sun.javafx.css.parser.CSSParser handleImport
All my styles from the CSS file test1.css are working. What I was curious about was the fact that my path style/common is showing up two times.
So I tried to change my imports to the following:
#import "style/common/test1.css";
#import "test2.css";
With these imports, both styles of the file test1 and the file test2 are working. But both files are still in the same package.
Whats happening here? Is there a known issue about the #import and probably a problem in the CSSParser?
It actually is a known issue:
https://javafx-jira.kenai.com/browse/RT-40346
There is a temporary fix available and the issue should be fixed in the next build Java8_u60.
The temporary fix can be made in the CSSParser class. Link to the git diff:
http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/839912277bf0
If you dont want to try the fix or wait for u60, just add all css files to the same folder and import it like that (temporary solution!):
#import "css/test1.css";
#import "test2.css";
#import "test3.css";
#import "testX.css";
Just contributing to the discussion (not directly to your question):
You don't have to explicitly set the full .css file path. All you need is to specify the .css folder and the file name:
Original path:
#import "css/nodes/path/CssFile.css";
Full path without folder specification:
#import "../../path/CssFile.css";
Both work the same. Notice that, in the second example, "../" refers to the path level, not the specific folder name.
So in your case, that would be
#import "../common/test1.css";

SCSS Partials for .css files without changing the filename

I'm looking for ways to optimize my WordPress instance. The theme has about 8-10 CSS files that are rendered in the functions.php. Consequently, I do not want to change any file names because that would mean that I have to hack the theme and I want to keep that to a bare minimum.
I want to use SCSS to combine these CSS files into one CSS file and include the new file in the theme instead. When I try...
#import "style.css";
#import "reset.css";
#import "shortcodes-styles.css";
It renders as
#import url(style.css);
#import url(reset.css);
#import url(shortcodes-styles.css);
How can I get SCSS to import the CSS as partials without changing the file names? I'm also using CodeKit if that makes a difference.
Not possible. Sass only compiles Sass files: https://github.com/nex3/sass/issues/556

Proper SCSS Asset Structure in Rails

So, I have an app/assets/stylesheets/ directory structure that looks something like this:
|-dialogs
|-mixins
|---buttons
|---gradients
|---vendor_support
|---widgets
|-pages
|-structure
|-ui_elements
In each directory, there are multiple sass partials (usually *.css.scss, but one or two *.css.scss.erb).
I might be assuming a lot, but rails SHOULD automatically compile all the files in those directories because of *= require_tree . in application.css, right?
I recently have tried restructuring these files by removing all color variables and placing them in a file in the root app/assets/stylesheets folder (_colors.css.scss). I then created a file in the root app/assets/stylesheets folder called master.css.scss which looks like this:
// Color Palette
#import "colors";
// Mixins
#import "mixins/buttons/standard_button";
#import "mixins/gradients/table_header_fade";
#import "mixins/vendor_support/rounded_corners";
#import "mixins/vendor_support/rounded_corners_top";
#import "mixins/vendor_support/box_shadow";
#import "mixins/vendor_support/opacity";
I don't really understand how rails handles the order of asset compilation, but it's obviously not in my favor. It appears none of the files realize they have any variables or mixins being imported, and so it throws errors and I can't compile.
Undefined variable: "$dialog_divider_color".
(in /home/blah/app/assets/stylesheets/dialogs/dialog.css.scss.erb)
Undefined mixin 'rounded_corners'.
(in /home/blah/app/assets/stylesheets/widgets.css.scss)
The variable $dialog_divider_color is clearly defined in _colors.css.scss, and _master.css.scss is importing colors and all my mixins. But apparently rails didn't get that memo.
Is there some way I can fix these errors, or will I need to resort to putting all my variable definitions back into each individual file, as well as all the mixin imports?
Unfortunately, this guy doesn't seem to think it's possible, but I'm hoping he's wrong. Any thoughts are greatly appreciated.
The problem with CSS is, you do not want to automatically add all files.
The order of which your sheets are loaded and processed by the browser is essential. So you will always end up explicitly importing all your css.
As an example, lets say you have a normalize.css sheet, to get a default look instead of all the horrible different browser implementations. This should be the first file the browser loads. If you just randomly include this sheet somewhere in your css imports, it will then not only override the browser default styles, but also any styles defined in all css files that were loaded before it. This goes the same for variables and mixins.
After seeing a presentation by Roy Tomeij at Euruko2012 I decided for the following approach if you have a lot of CSS to manage.
I generally use this approach:
Rename all existing .css files to .scss
Remove all contents from application.scss
Start adding #import directives to application.scss.
If you are using twitters bootstrap and a few css sheets of your own, you have to import bootstrap first, because it has a sheet to reset styles.
So you add #import "bootstrap/bootstrap.scss"; to your application.scss.
The bootstrap.scss file looks like:
// CSS Reset
#import "reset.scss";
// Core
#import "variables.scss";
#import "mixins.scss";
// Grid system and page structure
#import "scaffolding.scss";
// Styled patterns and elements
#import "type.scss";
#import "forms.scss";
#import "tables.scss";
#import "patterns.scss";
And your application.scss file look like:
#import "bootstrap/bootstrap.scss";
Because of the order of the imports, you can now use the variables, loaded with #import "variables.scss"; in any other .scss file imported after it. So they can be used in type.scss in the bootstrap folder but also in my_model.css.scss.
After this create a folder named partials or modules. This will be the place of most of the other files. You can just add the import to the application.scss file so it will look like:
#import "bootstrap/bootstrap.scss";
#import "partials/*";
Now if you make a bit of css to style an article on your homepage. Just create partials/_article.scss and it will be added to the compiled application.css. Because of the import order you can also use any bootstrap mixins and variables in your own scss files.
The only drawback of this method I found so far is, sometimes you have to force a recompile of the partial/*.scss files because rails wont always do it for you.
Create the following folder structure:
+ assets
|
--+ base
| |
| --+ mixins (with subfolders as noted in your question)
|
--+ styles
|
--+ ...
In folder base create a file "globals.css.scss". In this file, declare all your imports:
#import 'base/colors';
#import 'base/mixins/...';
#import 'base/mixins/...';
In you application.css.scss, you should then have:
*= require_self
*= depends_on ./base/globals.css.scss
*= require_tree ./styles
And as the last step (this is important), declare #import 'base/globals' in every style file where you want to use variables or mixins. You might consider this overhead, but I actually like the idea that you have to declare the dependencies of your styles in every file. Of course, it is important that you only import mixins and variables in the globals.css.scss as they do not add style definitions. Otherwise the style definitions would be included multiple times in your precompiled file ...
to use variables and such across files, you need to use the #import directive. files are imported in order specified.
then, use application.css to require the file that declares the imports. this is the way to achieve the control you want.
finally, in your layout.erb file, you can specify which "master" css file to use
example will be more helpful:
let's say you have two modules in your app that need different sets of css: "application" and "admin"
the files
|-app/
|-- assets/
|--- stylesheets/
| // the "master" files that will be called by the layout
|---- application.css
|---- application_admin.css
|
| // the files that contain styles
|---- config.scss
|---- styles.scss
|---- admin_styles.scss
|
| // the files that define the imports
|---- app_imports.scss
|---- admin_imports.scss
|
|
|-- views/
|--- layouts/
|---- admin.html.haml
|---- application.html.haml
here's what the files look like inside:
-------- THE STYLES
-- config.scss
// declare variables and mixins
$font-size: 20px;
-- app_imports.scss
// using imports lets you use variables from `config` in `styles`
#import 'config'
#import 'styles'
-- admin_imports.scss
// for admin module, we import an additional stylesheet
#import 'config'
#import 'styles'
#import 'admin_styles'
-- application.css
// in the master application file, we require the imports
*= require app_imports
*= require some_other_stylesheet_like_a_plugin
*= require_self
-- application_admin.css
// in the master admin file, we require the admin imports
*= require admin_imports
*= require some_other_stylesheet_like_a_plugin
*= require_self
-------- THE LAYOUTS
-- application.html.haml
// in the application layout, we call the master css file
= stylesheet_link_tag "application", media: "all"
-- admin.html.haml
// in the admin layout, we call the admin master css file
= stylesheet_link_tag "application_admin", media: "all"
According to this question, you can ONLY use application.css.sass in order to define import and share variables between your templates.
=> It seems to be only a matter of name.
An other way can be to include everything and disable this pipeline.
I had a very similar problem. What helped me was to put in the underscore to the #import statement when importing the partial. So
#import "_base";
instead of
#import "base";
It might be a strange bug...
My solution was to have an application.css.scss with all the imports:
#import "./inputs";
#import "./buttons";
#import "./rails";
#import "./base";
#import "./checked-border";
#import "./tailwind-extended";
#import "./helpers";
#import "./custom";
#import "./overrides";
And then add:
#import "./constants";
to the files that use the constants

Resources