Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rails 3.1, is it really impossible to avoid including duplicate copies of stylesheets?

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?

like image 618
ClosureCowboy Avatar asked Jun 21 '11 04:06

ClosureCowboy


3 Answers

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";
like image 96
emrass Avatar answered Sep 18 '22 21:09

emrass


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.

like image 37
David Avatar answered Sep 22 '22 21:09

David


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

like image 33
Paul Wellner Bou Avatar answered Sep 21 '22 21:09

Paul Wellner Bou