I am really struggling to structure the Sass files in a Rails 3.1 project to avoid massive duplication …
I have the following structure, with application.css.scss being imported as part of my main layout:
application.css.scss
- [*= require] main.css.scss
- [@import] 'variables';
- [@import]'bootstrap_overrides';
- [@import]'bootstrap';
- [@import]'base_elements';
- [@import]'superstructure';
- [@import]'modules';
So far so good. All these files are combined by sprockets into a single document. However I then want to modularise my Sass further, with page-specific files or files shared across regions of my site.
So on my GalleryResource#show page I need to use additional Sass files:
resource.scss
gallery_resource.scss
badges.scss
And maybe a css file from a lib:
gallery_lib.scss
These files need to reference a number of the files already imported in application.css. They need to make use of variables defined in variables.css.scss and of mixins defined in bootstrap. So I am forced to reimport these files in each file that uses them, causing massive duplication. I could write a manifest file for each and every page, but this is a maintenance nightmare and still results in duplication and two css files; application.css and page_specific.css.
So what is the solution? Do I need to dispence with application.css and move its imports into each page-specific file? So using the above example I would end up with a single manifest file that looks like this:
gallery_resource_manifest.css.scss
- [*= require] gallery_lib.css
- [*= require] gallery_resource.css.scss
- [@import] 'variables';
- [@import]'bootstrap_overrides';
- [@import]'bootstrap';
- [@import]'base_elements';
- [@import]'superstructure';
- [@import]'modules';
- [@import]'resource';
- [@import]'gallery_resource';
- [@import]'gallery';
- [@import]'badges';
I solved this by taking a cue from rspec, and creating a
_sass_helper.sasspartial, which contains all my non-direct-style imports (variables, mixins, placeholders), which is then included at the top of each file. The non-code bit is important, because if_sass_helper.sasscontained any styles, they would be written into each file.This effectively allows me to get the same “Sass environment” for each of my files, without any code duplication.
I have my tree organized like so:
Then, something like posts.sass would look like:
It works great. The post partials don’t need the sass helper, so I end up with one master file per controller, with partials for individual features, and the same environment everywhere.