How to import SCSS mixins in a Rails app? - ruby-on-rails

Trying to figure out how to import some SCSS files in a Rails 4 app. The files are:
#import "shared/mixins",
"shared/reset",
"shared/about-light";
I'm not sure how to do this properly and I don't know how to set the path either.
I put these files in a folder called "shared" and I put this folder inside of /lib/assets/css/ Is this the right way to do it?
Also tried to put the files in /vendor/assets/stylesheets/
How do I properly import these files?
Error:
File to import not found or unreadable: mixins.
Load paths:

We typically put mixins in a partial file called _mixins.scss directly in the app/assets/stylesheets/ directory, possibly under a subdir like shared if you want more organization. In your application.css you can then do (as you did)
#import 'shared/mixins';
#import 'shared/colors';
or whatever. If you really want them to sit somewhere else, you should look into the load_paths configuration setting for SASS. You can tell SASS where to look when it's importing files and probably lib/assets and vendor/assets are not included by default.
To add this configuration, in your environment.rb or other config file, you can do something like
config.sass.load_paths << File.expand_path('../../vendor/assets/stylesheets/')
which will make SASS look in vendor/assets/stylesheets in addition to all the other directories it searches in by default.

I think you are confusing partials and mixins.
From the Sass documentation:
Mixin
"A mixin lets you make groups of CSS declarations that you want to reuse throughout your site. You can even pass in values to make your mixin more flexible. You can think of a mixin like a function for css (awesome right!)." More about mixins here.
Partial
"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." More about partials here.
Therefore, what you are attempting to import are indeed partials and should be prefaced with an underscore.
Your directory structure should look like this:
assets
stylesheets
application.css.scss
shared
_mixins.scss
_reset.scss
_about-light.scss
And your application.css.scss file should look like this:
#import "mixins";
#import "rest";
#import "about-light";

Ok so I was able to work this out as follows:
In application.rb add the following:
config.sass.load_paths << File.expand_path('../../vendor/assets/stylesheets/')
In the CSS file import as:
#import "mixins",
"reset",
"about-light";
Put the files in to:
/vendor/assets/stylesheets/
Restart the server.

Related

SASS variables do not work when only imported into a master file

I have a partial sass file which holds mixins that I would like to access globally. My understanding is that all you need to do is #import this file into a master.scss file and it should be accessible globally. Sadly this isn't the case for me. I need to import the variable file into every individual .scss file I want to use it in. What do I nee to do to get so that importing it to the master.scss file I can access my mixins globally?
This is a rails app with my master.scss file imported into the application.scss file.
My assets tree
- scss
-- utilities
-- _mixins.scss
-- components
-- buttons.scss
master.scss
Contents of my master.scss file
#import 'utilities/_mixins';
#import 'components/buttons';
Contents of my mixins.scss file
#mixin square-size($size) {
height: $size;
width: $size;
}
Example of how I'm using the mixin in components/buttons.scss:
.square-button {
#include square-size(40px);
}
I'm not 100% sure it will resolve your problem but at least your code is cleaner this way.
Rename your button.scss to _button.scss and you don't need the write the underscore in #import 'utilities/mixins';
The underscore means the scss file is a partial. More info here: Why put in front of the file name "_" or "_" in scss/css?

Customizing Bootflat in Rails

I have installed bootflat using bower. The instaltion location was set up as "vendor/assets/components/Bootflat". I have also included the relevant files in my application.scss, application.js and application.haml files. I assume that it's being included correctly because everything is working as expected.
My question now is, how do I customize scss variables used in Bootflat? Here is my current code in application.scss (app/assets/stylesheets):
$alert-primary:red !important;
#import "Bootflat/bootflat/scss/bootflat";
"$alert-primary" is a variable that's already used by Bootflat and I want to redefine it. How/Where would I redefine this? I get that what I'm doing above is probably not right as the variable is defined by a Bootflat file, which would mean that my definition above is overwritten. But I also do not want to change the scss code in the origin files? What is the best solution? Will it be to copy and paste the code for a specific component into my app's stylesheet and then redefine a component after importing bootflat (this should overwrite the original definition by Bootflat)?

SCSS import relative to an imported stylesheet?

I've installed foundation-rails in my Rails app and run rails g foundation:install. The project-specific file(s) (mostly foundation_and_overrides.scss) are properly installed. The gem is there and it had no trouble installing, and the dependencies (SASS, Compass) are also there. But I'm getting:
Error compiling CSS asset
SASS::SyntaxError: File to import not found or unreadable: global.
Originating from:
/Users/local/.rvm/gems/ruby-2.0.0-p353/gems/foundation-rails-5.0.2.0/vendor/assets/stylesheets/foundation/components/_accordion.scss:1
After investigating, I've discovered that _accordion.scss was #imported in the main foundation.scss file, located two directories up in stylesheets/:
#import 'foundation/components/accordion'
The "missing" file, _global.scss, meanwhile, is in that same directory. If I then change the #import code in _accordion.scss from #import 'global' to #import 'foundation/components/accordion', it clears and moves on to the next error (there are a lot of sub-imports here).
It's clear that what's happening is SASS is looking for _global.scss relative to the top stylesheet, foundation.scss, and not relative to the imported stylesheet asking for it (_accordion.scss).
I can't imagine this is a bug in Foundation/Foundation-Rails – this gem wouldn't work for anyone – and I don't want to modify the gem's contents myself.
So my question: do I have to change some SASS settings to allow #import relative to an imported stylesheet? I don't want to modify this gem to make it work (I'd like to allow for future updates to the gem).
Edit
Clarification of directory structure within the gem's vendor/assets/stylesheets directory:
foundation.scss
foundation/components/_accordion.scss
foundation/components/_global.scss
Edit 2
You can actually see the gem's code and structure on github
Edit 3
Thought I'd solved the problem, but I didn't: changing from an #import to a =require got rid of the errors, and included Foundation's CSS. But require does not import the SCSS functionality - variables, mixins - that Foundation provides. There's no way to change global values this way, or to retrieve them or the mixins from the main stylesheet or other #imported stylesheets.
It looks like Foundation thinks this is the best possible solution:
Manually add Foundation's stylesheet subdirectories (each of them) to SASS's :load_paths in the main block of application.rb:
config.sass.load_paths += [
"#{Gem.loaded_specs['foundation-rails'].full_gem_path}/vendor/assets/stylesheets/foundation/components",
"#{Gem.loaded_specs['foundation-rails'].full_gem_path}/vendor/assets/stylesheets/foundation/"
]

Using variables and mixins in Foundation

I've found a lot of similar questions to this one but nothing that quite solves my problem. Basically, I'm using foundation 4.x with rails 3.x, everything is working fine with foundation_and_overrides being included in my application.css. I can modify the variables in foundation_and_overrides and it all works fine. However, I want to use the $primary-color variable (and a bunch of others) in one of my other scss files (application/global.css.scss). If i use #import "foudation_and_overrides" in my global css file, then it works, but it includes the entire Foundation CSS twice in my compiled application.css, which is obviously not ideal.
I also want to use mixins, such as #include radius() in my global file. This works if I use #import "foundation/components/global" - but then this also ends up with duplicate CSS being compiled. All I want to do is use the global vars & functions, not the CSS - surely this is a really common thing to do?
Previously (before foundation) I just put all my scss functions in a helpers file, and imported this in all other scss files that needed it.
Another quick Q while I'm here, what class do I use to add the little dropdown triangle thing next to some custom text?
Thanks!
With new foundation you do:
$include-html-global-classes: false;
#import "foundation/components/global";
Updated for even newer foundation (see commentS)
Earlier path was
#import "foundation/foundation-global";
As James said you can set the variable $include-html-classes to false and it won't copy any of the styles to the css. You can add the following lines to any scss sheet to get access to variables and mixins.
$include-html-classes: false;
#import "foundation";
There are a bunch of Sass variables named something like, include-grid-css or something like this in _settings.scss or _variables.scss. You can turn them off so it doesn't generate all of those standard presentational classes. If you are confused, just jump into the source of one these and you will see at the bottom of the file, there is an if statement that causes all of that css to be generated with the mixins at the top of the file. Hope this hepls.
Keep only settings in foundation_and_overrides.scss
Remove the following line at the end of the file foundation_and_overrides.scss:
#import "foundation";
And maybe rename foundation_and_overrides.scss to a more appropriate foundation_settings.scss.
Uncomment all settings that you will use in your SASS files. This also makes explicit which Foundation settings you will use in your application files.
Use #import in application.scss
In "application.scss" make sure to use #import instead of require for both Foundation and its settings.
/*
*= require_tree .
*= require_self
*/
#import "foundation_settings";
#import "foundation";
Use Foundation settings in your application files
You can simply add the following line in your files that need to access to Foundation variables:
#import "foundation_settings";
I haven't tested this with mixins yet, but for variables it works and prevents duplicated code.

Import SCSS files from parent directory on Heroku Cedar

I'm trying to deploy a Rails 3.1 app I was working on locally. But once deployed to Heroku (Cedar stack), I encounter an issue I wasn't having locally, and I can't find any solution to this.
Actually, in some of my SCSS files, I import other SCSS files located in the parent directory. Among the several syntaxes I tried :
#import "file.css.scss";
#import "file";
#import "/file.css.scss";
#import "/file";
#import "../file.css.scss";
#import "../file";
Most of these work locally, but none work on my heroku Cedar app. I also tried renaming my imported file into "_file.css.scss" with an underscore, as it seems it's the standard format for SCSS files made to be imported. But didn't change anything.
The error heroku logs are giving me is :
ActionView::Template::Error (File to import not found or unreadable: /mixins.css.scss.
I'm getting out of ideas right now, so would be thankful if you had any clues to solve this.
Thanks a lot,
Cheers !
The syntax should be
With the following folder structure
/app/
/assets/
/stylesheets/
/pages/
index.css.scss
products.css.scss
application.css.scss
If you wanted to include the scss files in /pages/ from application.css.scss you would do this:
#import "pages/index";
#import "pages/products";
You should also be able to do the following (however I'm not sure if this is limited to having Compass in the project or not).
#import "pages/*";
Being able to do glob imports is awesome. But I think it may be Compass only, or at least it used to be.
If the file your importing is within the same folder the following should work:
#import './file.css.scss';
I found it's important to have the relative path and file extension present when I ran into a similar issue. Since you were trying to use ../ that would look for the file your importing in the parent folder rather than within the same folder.
Your best bet is to use the built in Rails Asset Pipeline to handle including your style files.
In your app/assets/stylesheets folder you should have a file named application.css. This file uses Sprockets to automatically include all of your css files placed inside of the app/assets/stylesheets folder.
At the top of the file you'll see this:
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require_tree .
*/
The *= require_self part includes any css style written in this actual application.css file, while the *= require_tree . part includes assets found in app/assets/stylesheets.
If you'd like to change the order of inclusion, or specify a specific stylesheet, for example a file named mixins.css.scss located in app/assets/stylesheets, here is how you'd do that:
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require_tree .
*= require_mixins
*/
And the magic of sprockets will include your file for you.

Resources