How should you manage the organizing of css files and inclusions in a large ruby on rails application, assuming you're not using a framework? Naturally you'd have your application level styles (e.g. reset.css, applcation.css). But after that what's the best approach? I could see using controller specific sheets or more granular view specific ones. Are there other sensible options? What would be the pros and cons?
By the way, I'm working in pre 3.1 rails right now, and it seems like the inclusion of the asset pipeline may impact the answer here -- but am happy to hear solutions from either a pre or post asset pipeline perspective.
Thanks!
When creating a rails application we are welcomed by a not so blank canvas that will be used for code. In the sea of different files created we can follow the path app/assets/stylesheets and create a new file style. css under the stylesheets folder. This file can be called anything but make sure you end it with the .
Then we place it's corresponding CSS in this folder: /* app/assets/stylesheets/components/product_card. scss */ .
stylesheet_link_tag(*sources) Returns a stylesheet link tag for the sources specified as arguments. If you don't specify an extension, . css will be appended automatically. You can modify the link attributes by passing a hash as the last argument.
Moving this into answers because it's (just a bit) hefty for a comment, even though I realize it is not the exact answer you're looking for.
I haven't moved on to rails 3.1 yet, but I have been using Compass/Sass for quite some time, and I can loosely describe my (somewhat ever-changing) practices.
Check out Compass here: http://compass-style.org/
My goal is to be as modular as possible, and separate my styles into categories in several different ways. A sample structure might look like this. I'm embedding comments along with the file hierarchy, so hopefully it's readable.
- stylesheets
# at top level, the files which are eventually concatenated and output, the main
# sheet, "screen", a stripped version for a wysywyg editor, and some overrides.
- screen.scss
- print.scss
- ie.scss
- wysiwg.scss
# also in this folder I tend to keep a reset
- _reset.scss
# and then separated, "includes" and "partials", includes being purely definitions
# and mixins, while partials being their application (actual CSS output)
- _includes.scss
- includes
- _definitions.scss # some global variable defs
- _typography.scss # typography mixins and defs
- _colors.scss # colors mixins and defs, and so on
- ...
- _partials.scss
- partials
- _application.scss # top level layout + tweaks that don't belong anywhere else
- _typography.scss # the generation of typography CSS
- _colors.scss # the generation of colors CSS, and so on
- ...
- _layouts.scss
- layouts # layout specific styles
- _controllers.scss
- controllers # controller specific styles
- _modules.scss
- modules # modular, reusable pieces (widgets, breadcrumbs, navs, etc)
- _vendor.scss
- vendor # everything vendor, (jquery-ui, qtip, colorbox)
The basic idea is that everything gets compiled into the top level *.scss files, the only ones which aren't "partials" prefixed with an underscore. These files are very simple, and tend to look like this.
# screen.scss, import all partials
@import 'reset';
@import 'partials';
# wysiwyg.scss doesn't need all the partials, but needs the basic stuff
# and the semantic classes for wysiwyg users, e.g. ".red", etc.
@import 'reset';
@import 'partials/typography';
@import 'partials/colors';
@import 'partials/semantic';
_layouts.scss
and other files which share folder names are simple collective imports of the files in their respective directories.
The general idea is that partials stay as thin as possible, with the brunt of the work being done in mixins. Compass thankfully provides a full grab-bag of these as well which I make heavy use of.
For some this type of file structure may be unwieldy, but I find it works well for my purposes. Especially once you get a good library of mixins and swappable partials going. It makes it somewhat easy to tweak a few variable definitions or replace one partial or mixin with another for quick global changes.
In my projects I've got some helpers that load stylesheets and javascripts based upon controller and action. I also load the defaults, stuff in a common directory and a vendor directory. This is all done in my application.html.haml layout so that all of these includes are in the header.
assuming a controller named my_apps_controller.rb my stylesheets and javascripts directories looks something like this:
public/javascript/
vendors/
common/
my_apps/
common/
index/
edit/
show/
...etc...
My stylesheets/sass/ directory looks similar.
The benefit here is that I get a built in convention-based organization for my assets rather than having to play configuration games. The challenge is that I find cases where it's not clear what action directory it goes into. So far it's served me well though.
my helpers are basically:
module ApplicationHelper
def load_javascript_for_directory(directory_name)
glob_string = "#{directory_name}/**/*.js"
javascript_include_tag Dir.chdir(File.join(Rails.root, "public", "javascripts")) { Dir.glob(glob_string).sort }
end
def load_css_for_directory(directory_name)
glob_string = "#{directory_name}/**/*.css"
stylesheet_link_tag Dir.chdir(File.join(Rails.root, "public", "stylesheets")) { Dir.glob(glob_string).sort }
end
end
Nothing tricky, but in my application layout I can call them with:
= load_javascript_for_directory "#{controller_name}/#{action_name}"
This loads up controller/action specific assets and the normal boilerplate ones get the stuff I need regularly.
I'm not trying to sell this as the only approach. It's just one alternative that not only solves the problem for me, but it helps me really understand the structure of my assets and how to dry them out.
And yes, SASS for my stylesheets and coffeescript for my javascripts :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With