3/28/08
Don't you Sass me! At least not dynamically ...
Being a programmer at large, aka a freelancer, and a highly opinionated one at that, I am often struck by how often a new "language" or way of doing things is touted as the best way and everything else must be abandoned at all cost. My advice in short is don't do it.
Those who know me may think that a strange thing for me to say; after all I'm a Ruby programmer. However, that does not negate the points I'm about to make below.
Sometimes the inventors of these new trends are simply not taking advantage of the current technologies, or are inventing new ones because it is fun. There is nothing wrong with that. I love reinventing the wheel for the simple fact that I can. It's a great learning experience. But it's not always productive.
So now that I've got that out of the way, I'm going to pick a little idea of dynamic css using the technology called Sass. Sass is kind of a sub-project of the haml project that was built to shorten the amount of css you have to type by hand. Haml does the same for html. Again, not a bad thing. A little less time on one part of a project goes a long way to completing a project quicker. It's also cleaner, if you are a decent coder, and easier on the eyes. This could enhance maintainability. Kudos to the idea in that respect.
Here's where I take up my gripe. I first came across the idea as a way to dynamically replace aspects of the css, dependent on the environment. Dynamic css would allow us t expand a layout based on the browsers current size for instance. Great! But I something doesn't seem right about this ... Why do we need a new language to accomplish this when those who are using any framework, be it Ruby on Rails, Django, or even CakePHP, all have controllers, views, and template rendering engines, to handle dynamic layouts already? Can't we just feed some variables into the template from the controller and "viola!" instant dynamic layouts! Well yes, in fact we can.
You might as well load up your terminal, cd into your development directory, get textmate warmed up, and follow along. Here's a quick Rails [1] example.
In Terminal create the rails project:
Clean up a bit:
Now we going to create a controller that will act as our stylesheet condute so to speak, a method for the media type screen, and the corresponding css view:
So far all is fine with the world. Now would be a great time to ask, you have upgraded to rails 2.0 haven't you?
Moving on.
So now that we have the controller and view established let's move on to routing and environmental changes.
In config/routes.rb:
In config/environment.rb at the very bottom:
That should cover that. While we're at it we'll need a to point the root to a working controller. Let point it at the default application for the sake of simplicity (config/routes.rb):
And make an index def with layouts (apps/controllers/application.rb):
And touch a little view for it as well:
Now open up app/views/layouts/application.html.erb and let's toss in a generic 2 row, 1st row 1 column, 2nd row 2 columns, layout. We could also call this a header content layout or whatever. No snarky comments or you can just sit in the corner.
"You added crap in the header!" Ahhh! You're right! I did throw in a bit of advertising for one of my projects, Collegeprops, in the title. The site where you can find, post, rate, love, hate, and manage your apartments in Columbus, Ohio. But enough modest self/client promotion!
Oh, You meant the javascript stuff and the lack of a style sheet tag! Yeah, now that you mention it let's dive into that!
So why am I using javascript? Well I want the screen resolution of course. Further, I want it to be passed to the stylesheets controller, so what better way than to use javascript to write out the stylesheet tag with a few parameters such as height, width, and time (to prevent caching). The controller can then handle those through params quite nicely. Here's the code to paste in your public/javascripts/application.js:
We could also do for javascript what we are doing for css. But let's leave that alone for now. Don't get distracted Michael!
My lunch break is nearly over here so let's walk through the final steps.
Edit app/controllers/stylesheets_controller.rb (inside the screen def):
Edit app/views/stylesheets/screen.css.erb:
Ok. Load up the server and look at the beautiful mess we've created. Now apply these principles to a real layout and real code. You'll find a certain amount of freedom in being able to go "Dynamic" with technology you already use everyday. Not only will you not have to do anymore new studying, but you might just have that extra hour a day to get some exercise, breath some fresh air, and save days on trying to reinvent the wheel for clients on a deadline.
You can apply these same principles to Not do client editable templates in Liquid for that new engine your client wanted. Whatever. New technologies are fantastic, but long live the old ones too! Until my next sarcastic post, Cheers!
Oh, and here is the code if you want to download it in it's entirety: dynamic_css.zip
[1] nor
[2] howtocreate
Those who know me may think that a strange thing for me to say; after all I'm a Ruby programmer. However, that does not negate the points I'm about to make below.
Sometimes the inventors of these new trends are simply not taking advantage of the current technologies, or are inventing new ones because it is fun. There is nothing wrong with that. I love reinventing the wheel for the simple fact that I can. It's a great learning experience. But it's not always productive.
So now that I've got that out of the way, I'm going to pick a little idea of dynamic css using the technology called Sass. Sass is kind of a sub-project of the haml project that was built to shorten the amount of css you have to type by hand. Haml does the same for html. Again, not a bad thing. A little less time on one part of a project goes a long way to completing a project quicker. It's also cleaner, if you are a decent coder, and easier on the eyes. This could enhance maintainability. Kudos to the idea in that respect.
Here's where I take up my gripe. I first came across the idea as a way to dynamically replace aspects of the css, dependent on the environment. Dynamic css would allow us t expand a layout based on the browsers current size for instance. Great! But I something doesn't seem right about this ... Why do we need a new language to accomplish this when those who are using any framework, be it Ruby on Rails, Django, or even CakePHP, all have controllers, views, and template rendering engines, to handle dynamic layouts already? Can't we just feed some variables into the template from the controller and "viola!" instant dynamic layouts! Well yes, in fact we can.
You might as well load up your terminal, cd into your development directory, get textmate warmed up, and follow along. Here's a quick Rails [1] example.
In Terminal create the rails project:
rails dynamic_css
cd dynamic_css
Clean up a bit:
mv public/index.html public/index.html.default
touch app/views/layouts/application.html.erb
Now we going to create a controller that will act as our stylesheet condute so to speak, a method for the media type screen, and the corresponding css view:
script/generate controller stylesheets screen
mv app/views/stylesheets/screen.html.erb app/views/stylesheets/screen.css.erb
So far all is fine with the world. Now would be a great time to ask, you have upgraded to rails 2.0 haven't you?
Moving on.
mate .
So now that we have the controller and view established let's move on to routing and environmental changes.
In config/routes.rb:
map.connect '/stylesheets/:action.:format', :controller => 'stylesheets'
In config/environment.rb at the very bottom:
Mime::Type.register 'text/css', :css
That should cover that. While we're at it we'll need a to point the root to a working controller. Let point it at the default application for the sake of simplicity (config/routes.rb):
map.root :controller => 'application'
And make an index def with layouts (apps/controllers/application.rb):
def index
end
And touch a little view for it as well:
mkdir apps/views/application
touch apps/views/application/index.html.erb
Now open up app/views/layouts/application.html.erb and let's toss in a generic 2 row, 1st row 1 column, 2nd row 2 columns, layout. We could also call this a header content layout or whatever. No snarky comments or you can just sit in the corner.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Collegprops.com | Coming Soon</title>
<%= javascript_include_tag :defaults %>
<!--
I wrote a handy little javascript function to load the right style sheet view,
while still getting the screen resolution. Just copy the code below and
change the name of the style sheet to the style sheet view you are using.
-->
<script type="text/javascript">
load_style_sheet("screen");
</script>
</head>
<body>
<div id="header">
Give me a logo or something!
</div>
<div id="body">
<div id="left-column">
Stuff goes here
</div>
<div id="right-column">
<%= yield %>
</div>
</div>
</body>
</html>
Oh, You meant the javascript stuff and the lack of a style sheet tag! Yeah, now that you mention it let's dive into that!
So why am I using javascript? Well I want the screen resolution of course. Further, I want it to be passed to the stylesheets controller, so what better way than to use javascript to write out the stylesheet tag with a few parameters such as height, width, and time (to prevent caching). The controller can then handle those through params quite nicely. Here's the code to paste in your public/javascripts/application.js:
function load_style_sheet(sheet) {
width_height = get_width_height();
time = new Date(); time = time.getTime();
width = width_height[0]; height = width_height[1];
document.write(
"<:link href='/stylesheets/" + sheet + ".css?" + "width=" + width + "&height=" + height + "&time=" + time + "' media='screen' rel='stylesheet' type='text/css' />"
);
}
function get_width_height() {
// Thanks to [2] howtocreate.co.uk for the bulk of this function, and for
// feeding my laziness by giving this code so that I did not have to write the cross browser
// checks myself. Much obliged!
var myWidth = 0, myHeight = 0;
if( typeof( window.innerWidth ) == 'number' ) {
//Non-IE
myWidth = window.innerWidth;
myHeight = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
//IE 6+ in 'standards compliant mode'
myWidth = document.documentElement.clientWidth;
myHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
//IE 4 compatible
myWidth = document.body.clientWidth;
myHeight = document.body.clientHeight;
}
return [myWidth,myHeight];
}
We could also do for javascript what we are doing for css. But let's leave that alone for now. Don't get distracted Michael!
My lunch break is nearly over here so let's walk through the final steps.
Edit app/controllers/stylesheets_controller.rb (inside the screen def):
Resolution = Struct.new(:height, :width)
resolution = Struct.new(:height, :width)
@screen = resolution.new(params[:height].to_i, params[:width].to_i)
respond_to do |format|
format.css
end
Edit app/views/stylesheets/screen.css.erb:
body {
background-color: black;
}
#header {
clear: both;
width: 100%;
hieght: 50px;
background-color: green;
}
#body {
margin: 0px auto;
width: <%= @screen.width * 0.85 %>px;
}
#body #left-column {
float: left;
width: <%= (@screen.width * 0.85) * 0.25 %>px;
background-color: grey;
}
#body #right-column {
float: right;
width: <%= (@screen.width * 0.85) * 0.75 %>px;
background-color: white;
}
Ok. Load up the server and look at the beautiful mess we've created. Now apply these principles to a real layout and real code. You'll find a certain amount of freedom in being able to go "Dynamic" with technology you already use everyday. Not only will you not have to do anymore new studying, but you might just have that extra hour a day to get some exercise, breath some fresh air, and save days on trying to reinvent the wheel for clients on a deadline.
You can apply these same principles to Not do client editable templates in Liquid for that new engine your client wanted. Whatever. New technologies are fantastic, but long live the old ones too! Until my next sarcastic post, Cheers!
Oh, and here is the code if you want to download it in it's entirety: dynamic_css.zip
[1] nor
[2] howtocreate
Labels: coding, css, ruby, ruby on rails


0 Comments:
Links to this post:
Create a Link
<< Home