Presented at RailsConf 2007 in Berlin
Rails provides many built-in mime types that you can generate in your application. Unfortunately, CSS was forgotten!

Why would you want to generate CSS dynamically? As a programmer, it annoys me to repeat the same hex values all over my CSS documents. Even worse, I have to make notes to remind myself what colors I’m using.

Not only colors, but HTML tags themselves are repeated inside CSS documents when I need to specify a style for a child element. For example, if I want to set a style for a link inside a list item, I have to repeatedly mention the li tag.
li {
color: blue;
}
li a {
color: green;
}
li a:hover {
color: yellow;
}
Generating CSS dynamically also gives you the ability to make your web applications smarter. For example, here are two columns. Normally, your Rails application would have no way to find out how wide they are. But if you store the column widths in a database table and generate the CSS, then other parts of your application can query the database for that information.

I worked on a site where we used this technique. PNN gives you the option of dragging a photo between columns of a layout. When you do, the photo is dynamically resized to fit the column. You could do this by squishing the image with CSS, but instead, we sent back a photo that was perfectly sized for the column.
→ Short PNN Columns Screencast
CSS controls many aspects of a page’s appearance. You may want to generate only a part of the CSS, while leaving the rest to a designer. In the example above, we generated a small snippet of CSS to control the layout. The rest was accomplished with static CSS.

There are several plugins for working with CSS in Rails. The easiest way is to just use the ERb templates that are built into Rails already.
→ Short CSS with ERb Screencast
The benefits of this approach are:
I use the HAML plugin for my templates and it comes with the Sass engine for generating CSS. It’s much more powerful than ERb because it was built specifically for CSS. Fortunately, most of the elements mirror standard CSS syntax, so it’s easy to learn.

Sass works outside of the normal Rails controller system. Put your .sass files into public/stylesheets/sass and they will be converted to CSS when your application starts up.

Sass also solves the nesting problem. Just indent a declaration and it will generate the appropriate CSS for nested items (inside the menu element here).

↓

The best thing about it is…variables! You can define a color once and reuse it. Variables start with an exclamation mark, and you can reuse variables by putting an equals sign in the attribute declaration.

And you can do math! Add or subtract colors to generate darker or lighter shades.

There are many other features in Sass. You can split your code into separate files and they will be combined into a single document for production. You can even put variable declarations in one file and reuse those variables in other files.

This very blog is using Sass with Merb. I wrote a Stylesheet controller that looks something like this:

In other news, I’ll be in London this next week, attending the Future of Web Apps Conference.
I’m also going to be at the George Pub on Tuesday night, handing out PeepCode t-shirts! Several dozen Rubyists have already replied and will be there, too.
http://lrug.org/nights/2007/09/26/episode-4-deadly-vision/
I’ve also published the third part of the RSpec Screencast at PeepCode. The next is one on the git SCM and was edited by Git maintainer Junio C Hamano. I hope to publish it shortly after I return from London (week of October 10).
I’m also a Rubist that will be there. But … where the George Pub?
Cool yay!
So I’m now fooling around with SASS, but I have two questions…
1/ Is the CSS file meant to get updated automatically when the source SASS file is changed? Maybe I’ve set it up wrong.
2/ Is there a textmate SASS bundle? I’ve looked but no luck so far from Mr.Google.
thanks for the tip!
Just to answer one of my own questions…
Putting this in env will always check for updates when developing:
Sass::Plugin.options[:always_update] = true
Well that isn’t working as well as I’d hoped
But I see someone else has a similar issue ;)
http://groups.google.com/group/haml/browse_thread/thread/9ecb5117ce05d599/d959c19972745936?lnk=gst&q=always_update&rnum=1#d959c19972745936
Great rundown. I’ve been using haml and sass for a few months now, and it’s the perfect blend of simplicity and power.
Jason, there is a Textmate bundle for haml and sass, a quick G search turned up:
http://bjhess.com/bjhessblog/2007/05/31/installing-haml-bundle-for-textmate/
@Francesc: Directions to the pub are here: http://fancyapint.com/pubs/pub46.html
@jason: Yes, Sass doesn’t reload unless you reload a controller. I use my on controller in Merb, which solves this problem, but could be done in Rails, too.
@Jordan: I was using an older bundle that I found somewhere. I’ve added a few snippets which I hope to submit back to the bundle maintainer.
The nice thing is that both Haml and Sass are so concise that you really don’t need any snippets.
Can’t wait for the Git screencast :)
I’m really getting into HAML now after playing with merb. Great timing on the article, I’m currently learning the ins and outs of CSS.
Similar thing for Django
http://www.djangosnippets.org/snippets/432/
Are your screenshots of code from Xcode?
This is a bad idea:
@Crescent
#main ul :width 30px .ie6 & :padding 0pxThe last line there will output ”.ie6 #main ul { padding: 0px; }” For the designer, we’ve brought our hacks right next to where they are defined for the general purpose styling.It certainly doesn’t solve the problem, but it at least helps us cope with the complexity.
Good post! I needed to generate dynamic CSS once, and I though I was going crazy!!! :D Now, it’s good to know this can be a good practice!
Felipe Giotto
Ruby is a general purpose language. Sass is a DSL. My comments were directly mainly at it.
css is also a DSL. The problem domain css tries to address is separating presentation from document structure. css being a DSL, by definition, has omissions, irregularities, imperfections and maybe even some oversights (like variables for example) compared to a general purpose language. You know what? Layering Yet-another-DSL on top of it doesn’t help in the long run. You’re at risk of abstracting away a DSL with another DSL.
I guess I’m realizing that maybe my issue isn’t with dynamic css per say; Sass (and dry-css) are elegant and look dead-easy to learn (and remember 6 months down the road!). It’s more that I don’t think the problem of repeating hex values and element selectors in my css is large enough of an issue to warrant the architecture of another DSL inside rails. There MUST be bigger fish to fry elsewhere in my application.
Sass++, I don’t know how many times I gave up with some css layout and handed it over to a real designer because I got frustrated changing umpteen values to try a different center column width or something like that.
We definitely have bigger fish to fry on our app, but Haml & Sass are small tasty fish and frying them first leaves more time for the big stuff as we’re not writing any more html/css than we need too.
looking forward to the event, can’t wait!
John.
You should really get on Edge Rails :-)
Awesome! I didn’t know that was in the trunk.
this page is completely broken in ie6
Really helpful stuff… Thanks!
@xin
uh every page is completely broken in ie6. use a real browser.
I can only find a bundle for HAML, is there one for SASS also?
“every page is completely broken in ie6. use a real browser.”
Dude, IE6 hasn’t been a “real” browser for YEARS.
Cool Tip. Thanks for the information
Hi. I`m looking this font:
http://nubyonrails.com/system/images/Berlin.035-001.png
Can someone tell name, link ?
Hi. I`m looking this font:
http://nubyonrails.com/system/images/Berlin.035-001.png
Can someone tell name, link ?
Lovely fonts, thanks for info :D
the font is bitstream mono vera sans
That’s perfect summary, very valuable for my next job of doing SEO friendly urls through htaccess. Thank you.
Excellent SITE. I will refer people to your ITEMS. Effective use of Wordpress had some exceptional. Cheers
i’d suggest, if you define your background-color then also define a contrasting foreground color. ground-rule of css and a warning in every validator.
(to be explicit: i can’t read the text on this page because my browser has default background black and text white. now you set the background white (or very light grey) but the text not black…)