I'm new to LESS and Bootstrap and I'm confused at the outcome of my css file.
My basic goal is to use the mixins and variables in bootstrap in my own css files.
From my understanding the process would be, get the less files, import them into the project, and import the bootstrap reference. So at this point I can now use the mixins in my own css file.
Example:
#import "less/bootstrap.less";
.myRow{
.make-row();
}
However now I have a 7400+ lines of styling in myCustomStyles.css. Is this "correct"? I don't understand why it actually imports all the styles. My understanding is... that I have a reference to bootstrap.min.css CDN or local. Then myCustomStyles.css will be included AFTER that and override the default values.
I guess I'm confused at how do I take advantage of a CDN and still use the mixins and variables in bootstrap?
I've used the following two articles as a reference:
http://www.helloerik.com/bootstrap-3-less-workflow-tutorial
http://www.codeproject.com/Articles/594098/How-to-customize-Twitter-Bootstrap-to-fit-your-web
Bootstrap.less is the full bootstrap implementation. It is going to have all the variables and mixins to build the entire CSS for bootstrap. If you don't want this, then you should probably pick and choose which LESS files to include instead. You probably want variables and mixins, so you could maybe get by with only importing variables.less and mixins.less?
If you look at bootstrap.less it looks like this:
// Core variables and mixins
#import "variables.less";
#import "mixins.less";
// Reset
#import "normalize.less";
#import "print.less";
// Core CSS
#import "scaffolding.less";
#import "type.less";
#import "code.less";
#import "grid.less";
#import "tables.less";
#import "forms.less";
#import "buttons.less";
// snip...
It is nothing but a bunch of imports to other .less files. Each file is sort of specific to what it is doing. At a minimum I think you would need variables and possibly mixins. Normalize does a CSS reset. Grid defines the grid classes, etc.
Possible Since LESS 1.5
You can specify that you want the code only as a reference like so:
#import (reference) "less/bootstrap.less";
.myRow{
.make-row();
}
The addition of the (reference) tells LESS to import it by not compile the code to CSS. This allows you to use the entirety of bootstrap for mixin reference purposes, but avoids adding all the code in. Of course, one needs to know how this may affect the implementation, as there are parts of bootstrap that expect certain code to be in place to work properly. But that this a whole other thing.
Related
I am trying to use Foundation 5 in a Rails 4 app. The problem I am having is I would like to have some custom CSS in addition to Foundation. In my CSS I would like to use some of the variables from Foundation. To use them I did added the following to the top of my scss file
$include-html-classes: false;
#import "foundation/components/global";
This works great except there is some junk still included on each page. According to https://github.com/zurb/foundation/issues/1629 this shouldn't happen.
If you look at the source here https://github.com/zurb/foundation/blob/master/scss/foundation/components/_global.scss then you can see that the meta stuff starting at line 284 will be included.
This is a problem since it will be included on every page that I want to use the variables/mixins on. Rails 4 combines all the css files into one which will have this same code over and over again...
Is there any way to include this file without it including any text?
I just discovered that using
#import "foundation/functions";
#include exports("global") {}
#import "foundation/components/global";
will include all the variables and mixins but won't add anything to your scss file!
I believe this is because the exports function is there to prevent css from being duplicated every time the global file is included. By having the fake exports function call it thinks it's already added the css.
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.
I'm having an issue with using #import to load global variables and also for the purpose of #extend from other files.
Let's say I have a settings.css.scss and I want this available in all my files by using #import 'settings'; at the top of each other scss file.
This works fine and I do get proper access to all my variables and stuff -- but doesn't this inject all the styles again to each file?
When I look at the source in the after-compiled version, I'm seeing the same style for a given class repeated 3-4 times in firebug, except it's scratching out all but one.
Is this repetitive bloat normal or am I doing something wrong??
I really don't know how to debug this, maybe somebody has an idea.
I have many LESS files which I import in application.css.less. We use Bootstrap, and we want to use the variables that are defined in it within our own styles, so we can't require the LESS files in the manifest (as required files don't seem to make their variables public to other required files).
Everything works nicely, except a few of the LESS files - when edited - don't trigger a recompile of the CSS! It seems to be quite random which do and which don't, and it's only 6 of them which don't (compared to about 25 in sum). When I require one of them in the manifest, it successfully leads to a recompile - if I #import it, it doesn't.
Any idea on how to debug this? If I rename one of them (e.g. from time_records.less to time_records2.less), it successfully trigger recompile after changes... So it has do do something with the names of these 6 specific files:
calendars.less
contacts.less
folders.less
handout.css.less
print.css.less
time_records.css.less
Any help is greatly appreciated. Thank you.
The latest edition of less-rails implements Import Hooks that should solve your problem. I realize this is a late answer and it may have not existed at the time.
Import Hooks
Any #import to a .less file will automatically declare that file as a sprockets dependency to the file importing it. This means that you can edit imported framework files and see changes reflected in the parent during development. So this:
#import "frameworks/bootstrap/mixins";
#leftnav { .border-radius(5px); }
Will end up acting as if you had done this below:
/*
*= depend_on "frameworks/bootstrap/mixins.less"
*/
#import "frameworks/bootstrap/mixins";
#leftnav { .border-radius(5px); }
The depend_on Directive
depend_on path declares a dependency on the given path without including it in the bundle. This is useful when you need to expire an asset's cache in response to a change in another file.
I'm running into an upsetting issue when trying to share variables and mixins across Sass stylesheets.
If I use #import to include a global stylesheet – one which includes global colors, mixins, etc. – it gets included again when Rails combines all stylesheets referenced in the manifest file.
Alternatively, if my manifest file does not include the global stylesheet, but multiple files in the manifest import it, the global stylesheet will still be included more than once. GAH.
How can you get around this? Does Sass have secret inclusion guards? Am I doing something terribly wrong?
I do not understand why this is an issue for your specific question. Variables and mixin declarations should not lead to any selectors or declaration blocks in your generated css file. However, when you use mixins for multiple selectors, the corresponding declarations are included for every such selector. This is how SASS handles it.
So as long as it's only variables and mixins, it should not matter if they are included multiple times in the manifest file since this does not have an effect on the compiled file. On a site-node, I believe it to be good style that SASS forces you to explicitly declare each file's dependencies.
If, however, you also have selectors and declarations in the base file that you want to inherit from in separate files, then indeed these will be included multiple times even in the compiled file. It would still be interesting to know how to prevent this by configuration. However, if you treat each of your sass files to be one encapsulated set of rules without cross-file inheritance, then you should be able to prevent your issue by convention.
For example, when using bootstrap-sass, just the mixins and variable definitions can be brought in scope with;
#import "bootstrap/variables";
#import "bootstrap/mixins";
You can get around this by doing this:
/*
* application.css.scss
*= require_self
* ----> Note the missing = require_tree
*/
#import "global.css.scss"; // Defines global mixins etc
#import "users.css.scss"; // Uses mixins defined in _global.css.scss
Then don't import global.css.scssinside users.css.scss or any other dependent files.
If you haven't already, check out Ryan Bates screencast on SASS and sprockets in rails 3.1, this is what he does to solve this issue.
For now, until SASS 4 is released, I prefer modifiying the import lines to something like:
#if not-imported("font") { #import "font"; }
You will need a function named not-imported then, of course, looking like this:
$imported-once-files: () !default;
#function not-imported($name) {
$module_index: index($imported-once-files, $name);
#if (($module_index == null) or ($module_index == false)) {
$imported-once-files: append($imported-once-files, $name);
#return true;
}
#return false;
}
This works fine and maintains the interoperability with other tools (like StyleDocco). I wrote about it, here
It is currently not possible to use SASS to include files dynamically. #import cannot be used within control directives (e.g. #if) or mixins, using a variable in an import directive is erroneous syntax, and there is no directive for ending file execution early (which effectively would allow conditional imports). However, you can solve your issue by changing how you structure your style rules.
NOTE
There is a SASS plugin that will modify #import to only
include files once. However,
Your code will have added dependence on the environment
We would all do better to understand how style rules are intended to be structured, which would avoid any duplicate rules.
#import may soon be deprecated. The SASS team is planning "large-scale redesign of importing", so re-import protection
might be part of future versions of SASS, as it is popular
requested feature.
Solution
If you have styles that are conditionally included from multiple files, they are not 'global' styles. These styles should be encapsulated in mixins, in 'module' or 'library' files. The main idea is that importing one such file will not output any css. This way, you can import these files redundantly so you can use the mixins wherever you need them.
If you need to do this with variables, then:
Make sure you define variables before including mixins, otherwise they are only available in the mixin scope. A good way to do this is to define all default variables in a vars.sass file, and import it along with imported modules/libraries so the variables are available globally.
Define variables using !default in the mixin, so it can be overridden even before the mixin is called (like in a vars.sass file).
If you have top-level styles that you want to ensure are defined without having rigid inclusion rules, you can use this mixin:
$was-defined: () !default;
#mixin define-once($name) {
#if not index($was-defined, $name) {
$was-defined: append($was-defined, $name);
#content;
}
}
// Example:
#include define-once('body-typography') {
body {
font-size: 100%;
line-height: 2em;
color: #444;
font-family: monospace;
}
}
For more good practices on structuring your code like this, check out this article.