Mon 30 Jan 2006
I just realized the benefit of something I saw a while ago in a Rails ticket. It is mostly about acts_as_vertical, which is cool and has its uses, but what I’m talking about now is the dynamic StylesheetsController. The way it works in the ticket is that it renders stylesheet based on database values and caches the resulting CSS file.
For CSS this is sort of a novelty until you really become a nazi about the one-place-for-any-given-piece-of-information rule as espoused by the Pragmatic Programmers. When reading about the holy grail of 3-column layout at A List Apart, it struck me that the CSS he’d written, while quite simple, encoded the same pieces of information multiple times - namely widths and padding.
My solution was to reinvent the StylesheetController, which I only later realized I’d seen before. My version looks like this:
class StylesheetsController < ApplicationController
caches_page :content
def content
headers['Content-Type'] = 'text/css'
render :action => params[:name]
end
end
It requires a route that looks like this:
map.connect 'stylesheets/:name', :controller => 'stylesheets', :action => 'content'
Now move your style.css from /public/stylesheets to app/views/stylesheets and rename it style.css.rhtml. Not the prettiest thing ever, but without a new template extension that’s what we have.
Perhaps more important is the realization that this works just as well for javascript files. Now I can use all the Rails helper goodness to construct my static javascript files! How awesome is that? Why hello visual_effect. Hello remote_function.
In case you’re interested, here’s my style.css.rhtml from the article:
< %
right = {:width => 130, :padding => {:horizontal => 10}}
left = {:width => 180, :padding => {:horizontal => 10}}
center = {:padding => {:vertical => 10, :horizontal => 20}}
[right, left, center].each do |column|
column[:full_width] = column[:width] + 2 * (column[:padding][:horizontal] || 0) rescue 0
column[:padding] = {:horizontal => 0, :vertical => 0}.merge(column[:padding])
end
-%>
body {
min-width: < %= 2 * (left[:full_width] + 2 * center[:padding][:horizontal]) + right[:full_width] %>px;
}
#container {
padding-left: < %= left[:full_width] %>px;
padding-right: < %= right[:full_width] + 2 * center[:padding][:horizontal] %>px;
}
#container .column {
position: relative;
float: left;
}
#center {
padding: < %= center[:padding][:vertical] %>px < %= center[:padding][:horizontal] %>px;
width: 100%;
}
#left {
width: < %= left[:width] %>px;
padding: < %= left[:padding][:vertical] %>px < %= left[:padding][:horizontal] %>px;
right: < %= left[:full_width] + 2 * center[:padding][:horizontal] %>px;
margin-left: -100%;
}
#right {
width: < %= right[:width] %>px;
padding: < %= right[:padding][:vertical] %>px < %= right[:padding][:horizontal] %>px;
margin-right: -< %= right[:full_width] + 2 * center[:padding][:horizontal] %>px;
}
#footer {
clear: both;
}
/*** IE Fix ***/
* html #left {
left: < %= right[:full_width] %>px;
}
June 19th, 2008 at 12.20
:) before I found this article I just did more or less the same thing, but without rails, using a template made with CSS comments instead of the figures and then find & replacing them all. Low-tech solution!
(p.s., do you think there might be a way to use RoR to fix the equal columns problem? Something involving having each column’s height set as a ruby variable then calculated… I’m completely new to it so have no idea how it might work, just seems like something that might be possible and might fix the ALA Holy Grail’s compatibility and falling-apart-when-resized issues?)