Dynamic CSS with Rails
October 24th, 2008
I’ve sometimes wondered why CSS isn’t more dynamic.
Take, for example, the styles applied to the sub-menu on the services page of this site. To achieve the highlighting of the current service, I combine a Rails view and CSS as follows:
The Rails View
<div id="<%= @current_service.name %>"> <div id="secondaryNav"> <ul> <% @services.each do |service| %> <li class="<%= service.name %>"><%= link_to service.heading, service_path(service) %></li> <% end %> </ul> </div> </div>
The CSS
#agileweb #secondaryNav .agileweb a, #java #secondaryNav .java a, #coaching #secondaryNav .coaching a, #mentoring #secondaryNav .mentoring a, #overview #secondaryNav .overview a, #advice #secondaryNav .advice a { color: #99CC00; text-decoration: underline; }
Handling a new service
That does the trick nicely until I decide to add a new service. Wouldn’t it be nice to have that CSS regenerated dynamically whenever I create, update or delete a service?
Enter a new Ruby module:
# lib/dynamic_css.rb module DynamicCss def generate_services_nav_links_css return if RAILS_ENV == "test" FileUtils.cd File.expand_path("public/stylesheets", RAILS_ROOT) File.open("servicesnav.css", "w") do |out| service_names = [] services = Service.find :all services.each { |s| service_names << s.name } service_names.each_with_index do |name, i| out.print "##{name} #secondaryNav .#{name} a" if i + 1 < service_names.size out.puts "," else out.puts " {" end end out.puts " color: #99CC00;" out.puts " text-decoration: underline;" out.puts "}" end end end
Then a small adjustment to invoke the css regeneration via a filter in my admin services controller:
class Admin::ServicesController < AdminLayoutController include DynamicCss after_filter :generate_services_nav_links_css, :only => [:create, :update, :destroy] # remainder of controller end
Lastly, to ensure that the servicesnav.css file exists by the time one of the public services pages is requested:
# config/initializers/services_nav_css.rb include DynamicCss generate_services_nav_links_css
Admittedly this is a specific case, but this example shows that it is relatively straightforward to dynamically generate CSS within a Rails app if required.
Navigation
Latest Blog Posts
- 11 Aug: RVM, Bundler and Ruby Tracker
- 10 Feb: Ten Years On
- 10 Oct: Configuring CapGun
- 6 Sep: Inspirations for a Ruby DSL
- 28 Jul: At Your Service
Syndication
Tags
actionwebservice automated testing bdd blog bundler capgun capistrano collaboration css cucumber deployment dsl estimating jaoo javascript osdc osdc2008au pdf prawn rails railscamp rake rest rorosyd rspec ruby ruby tracker rvm selenium services syntax highlighting tdd technology unconference wds08 web design webrat xml xml-rpc