Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you manage css stylesheet files and inclusions in a large ruby on rails application?

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!

like image 784
tks Avatar asked Aug 18 '11 23:08

tks


People also ask

How do you add a CSS file to Ruby on Rails?

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 .

Where is CSS file in rails?

Then we place it's corresponding CSS in this folder: /* app/assets/stylesheets/components/product_card. scss */ .

What is Stylesheet_link_tag?

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.


2 Answers

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.

like image 92
numbers1311407 Avatar answered Oct 14 '22 00:10

numbers1311407


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 :)

like image 43
jaydel Avatar answered Oct 14 '22 01:10

jaydel