Not Invented Here
I swiped this idea from the work Craig Ulliott did on bodyshopbids.com. Thanks Craig!
Don’t hard-code selectors for action and controller specific CSS and Javascript
Sometimes you need a bit of CSS or javascript that only applies to a specific action, or maybe to every action on a controller. So, you go in and add a class or an id to every view that controller supports.
Then you sigh.
You can do something like this instead:
%body{:id => body_id, :class => body_class}
where body_id and body_class are helper methods. For TroopTrack, these methods look like this:
def body_id body_id = controller.class.name.sub(/Controller$/, '') .sub(/::/, '').underscore+'_page' body_id.sub!(/^devise_/, "devise_#{controller.scope_name}_") if body_id.match(/^devise_/) return body_id end def body_class if @body_class.nil? @body_class = "" end @body_class << " #{controller.action_name} " @body_class << " #{controller.class.name.split("::").first.downcase}" unless controller.class.name.index("::").nil? @body_class << " unit_type_#{@troop.unit_type_id}" if @troop return @body_class end
I think TroopTrack’s helpers are a bit overly complicated, but that’s because many of them exist in a namespace and I want a class for the namespace as well as the controller. I also need to adjust my CSS based on the type of unit they are, so that’s in there too. Here’s an example body tag from TroopTrack:
<body class=' index share unit_type_3' id='share_share_page'>
Index is the action. Share is the name space. Unit_type_3 means it’s a cub scout pack. The id, share_share_page, means it’s on the share controller in the share namespace.
Sometimes when I write a blog post and share my code I see opportunities to dry things up or refactor them. This is one of those moments.
A more reasonable place to start would be something like this:
def body_id controller.class.name.sub(/Controller$/, '').sub(/::/, '').underscore end def body_class controller.action_name end
As usual, I’m suspicious that there is a ruby or rails idiom out there that can make that code better. I’m all ears.
With this in place, it’s very easy to override CSS or write javascript that is specific to a given page. If you are following the Rails 3 convention for assets, you could just add this scope to the beginning of every controller-specific CSS and javascript file so that you are forcing the behaviors in those files to only apply to the controllers they relate to. I’m not a big fan of this per se, but I don’t condemn it as a practice either.
Don’t Overdo It!
It’s easy to let this get out of control and start putting every new bit of CSS you write inside a selector so that you don’t accidentally mess up something else. Please don’t fall into this trap. It only makes your CSS worse and will eventually lead to inconsistency in your site styling. Instead, if you can, take the time to make sure you are building a clean and consistent set of styles for your site and use the selectors only when you truly need to override something.

0 responses so far ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment