Maybe I don't understand how to use mixin with sass, or how to work with the ones with bootstrap-sass (https://github.com/thomas-mcdonald/bootstrap-sass). But how can I do something like change the box-shadow on a class of input fields?
EDIT: Should clarify, in this example I'm trying to change the glow effect on an active input field when it is selected. By default it's blue.
For my project setup, I have it just like it says on the github page and have the gem in the Gemfile and then in a controller I have something like:
#import "bootstrap"
.testInput {
/*(here I have put a variation of variables that I change to see
if I can do something with the mixin like $bordercolor: #000;*/
#include formFieldState()
}
So maybe my understanding of how sass works is way off. I guess if I wanted to change the box-shadow for inputs I could just repeat the code in my own mixin but it was also just kind of a general question on if this kind of thing was possible with the other mixins as well.
Did you look at the source to see what the formFieldState mixin does? It lives here: https://github.com/thomas-mcdonald/bootstrap-sass/blob/master/vendor/assets/stylesheets/bootstrap/_mixins.scss#L159. It looks like this mixin is designed to be used within some type of container, most likely a form.
There are no variables controlling the default input:focus box-shadow (its declaration is here: https://github.com/thomas-mcdonald/bootstrap-sass/blob/master/vendor/assets/stylesheets/bootstrap/_forms.scss#L126). You'll have to override it the old fashioned way.
You should put the things you want to change after the #include, instead of before. The last declaration wins with CSS so if you put them before the mixin, the mixin version will win.
See here: http://www.vanseodesign.com/css/css-specificity-inheritance-cascaade/ for an advanced discussion of CSS precedence.
Related
rails 3.2
I am new to slim, and I have to work with an application that's using it. Reading through some documentation, I see that using something like:
.class
which translates to:
<div class="class"></div>
In the code I inherited, in the .html.slim file, I have:
.form-section.customer_info
When I look through the stylesheets folder, I cannot find customer_info, but I can find form-section.
Shouldn't I be able to find customer_info in one of the stylesheets?
The answer is maybe you can find it in a stylesheet. But there are other cases, where you may not:
Sometimes a class is used as a target for a JavaScript snippet; if you find it mentioned in the javascript for the app, then you likely want to keep it because an interaction may depend on it (read the JS code to determine this).
Sometimes, the class has been removed from the stylesheet and not removed from the code; in this case you may remove it.
However, sometimes a class is added to mark the section of HTML as semantically significant so that styling can be applied to it at a future time; in that case, you may choose to keep it.
For instance, for better or ill, when I am writing code, I will name sections using classes, as .user-list or .part-table to indicate that, as the coder, I know the HTML code is going to contain users or parts. By doing this consistently I can mark out portions of the front end for later consistent styling by usage; that is, all the part tables can be styled the same way, all the user lists can be styled the same way, etc. Again, this is a convention I have seen used and that I practice. Nonetheless, these represent a few reasons why a class may be present in the HTML, but not referenced elsewhere.
I am using bourbon and neat gems for create the design of a rails application. My application.css.scss contains this:
#import "bourbon";
#import "neat";
#import "main";
But if I run 'rake assets:precompile' then happens this error:
rake aborted!
Undefined mixin 'outer-container'.
(in /Users/anonymous/example/app/assets/stylesheets/admin/main.css.scss)
/Users/anonymous/example/app/assets/stylesheets/admin/main.css.scss:5:in `outer-container'
/Users/anonymous/example/app/assets/stylesheets/admin/main.css.scss:5
The file main.css.scss contains this:
footer#page_footer {
#include outer-container;
nav{
#include span-columns(6);
#include shift(3);
section#about_me_footer, section#contact_footer, section#miscellaneous_footer {
#include span-columns(2 of 6);
}
}
p {
#include span-columns(6);
#include shift(3);
}
}
Someone can give me some suggestions?
I was having the same problem. I was able to get it working in two different ways.
The first way is probably less desirable but you can add your code right in the application.css.scss file:
div.container {
#include outer-container;
}
Alternatively, you can add:
#import "bourbon";
#import "neat";
To the top of your main.css.scss file.
This allows you to keep your styles organized.
The bourbon site links to a page in their wiki regarding this problem, but the solution mentioned didn't work for me:
https://github.com/thoughtbot/bourbon/wiki/Rails-Help-%5C-Undefined-mixin
I had this same problem. The solution for me was to rename a partial file from layout.css.scss to _layout.css.scss. Any files making use of SASS mixins need to be included after those mixins are loaded in. In this case it was trying to precompile the layout.css file alone, though it did not require the source of the mixins it was referencing. Adding the underscore makes the precompiler ignore that file until another file requires it.
According to the Change Log the outer-container mixin has been removed as of version 2.0.0. The highest version you can use with outer-container is 1.8.0. When adding Neat via Bundler, you will get 2.0 or higher unless you specify a version in your Gemfile.
The new way to do this looks much simpler, but that's little comfort if you have a bunch of unsupported scss.
FWIW this is the issue reported https://github.com/thoughtbot/bourbon/issues/120, Using jacklin's comment about adding the import statements directly to my main css file resolved it. However, I'd like to have this problem fixed since I dont really want to keep adding those import statements to each file I wish to use the mixins for
I have had the same problem.
I had a div using #include outer-container, and a second div containing #include span-columns(8). The second div incorrectly sat outside the first, producing the misleading error "Undefined mixin 'outer-container'". Moving the second div inside the first (within the outer-container - in the CSS and HTML) corrected the problem.
For the problem above, you must do the same thing by making sure the p tag is a child of the footer.
I have situation where I generate stylesheets based on information in the database. This means I have a views/users/show.css.erb which contains code like:
a {
color: <%= #user.favorite_color %>;
}
Fair enough, works perfectly with a respond_to { |f| f.css } in my controller. However now I would like to use some of SASS's sassy functions like lighten, darken etc. in my CSS, so I would like to have SASS parse my view. However I cannot figure out how to register SASS as a template handler in my views without too much ugly hacks. I just don't get how it works. Has anyone ever tried this?
I have tried including SASS's Functions module but to no avail.
I was planning of doing the same for dynamic user themes some time ago. Back then, I found a mailing list answer to a similar question to yours, by Nathan Weizenbaum (author of SASS) which got me back on the straight and narrow:
On Mar 18, 11:46 am, Nathan Weizenbaum wrote:
There's a reason Sass doesn't allow dynamic access to Rails code - see
the Sass section ofhttp://haml.hamptoncatlin.com/docs/rdoc/files/FAQ.htmlfor
a brief discussion. Sass is also fairly slow, since it's only compiled once,
so this is probably far too slow for a production environment.
The link is not working anymore, but the SASS FAQ has only one section called Can I use a variable from my controller in my Sass file? which answer the dynamic question:
If you really, really need to compile Sass on each request, first make sure you have adequate caching set up. Then you can use Sass::Engine to render the code, using the :custom option to pass in data that can be accessed from your Sass functions.
So in general, SASS is not designed for dynamic css generation on each request. Rather it is intended to be used as a pre compilation solution to generate static css files.
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.
Starting a new rails project and we have a well-thought-out color palette, and want to capture that in one place. I have usually kept colors in the CSS, but I find I end up with all the same color in lots of different selectors, as it shows up as a background color, color, border color, etc. I also will occassionally need access to colors in the Javascript. It would be great to just define each color ONCE.
So I'd just like to define my color palette in a way that's re-usable in the CSS and Javascript, but I don't want to go all the way to SASS, abandoning CSS syntax completely.
Is there a rails plugin already made that allows this? I could patch together an ERB type solution, but I don't want to do it if someone else has something readily available.
There is a new project out called {less} that sounds like what you are looking for: http://lesscss.org/
LESS seems to have a rails plugin, and a more css like syntax.
There are several server side parsers like LESS and SASS, but if you want to use the palett mentality in straight CSS you have to revers your thinking. Define basic styles like colors, fonts etc. and apply multiple classes at the tag level.
[style]
.color1{color:red}
.color2{color:blue}
.color3{color:green}
.bcolor1{color:red}
.bcolor2{color:blue}
.bcolor3{color:green}
[/style]
[tag class="color1 bcolor2"]
This has worked very well for us.
Another (pure CSS) way may be to define each color once, and have the several selectors associated with that oe color definition, for example:
body,
p,
#foo,
.bar {color: #802369 }