Don't use css or table layout, use Sass and Compass

Posted by Guillaume Maury
on Feb 04, 09

Sorry for the tongue in cheek title, I’m trying to bait the news.ycombinator crowd who got into another spiraling argument. Last time it was did php win? now it’s CSS vs tables (this one is a recurring one).

But, I have the solution to end this religious war, use compass and sass!

Ok, just a summary for those too busy to read:

  • I’m not a designer and having to get the layout right is the activity I hate the most when making a web application
  • I feel that a lot of shortcomings of CSS can be solved by using a framework like BluePrint
  • But using blueprint negates the benefits of using semantic markup (since you start having weird classes like span-6 prepend-2)
  • Sass has a nifty feature called mixin and Compass use it to provide the power of frameworks like BluePrint while still keeping semantic classes

So now let’s get on with a tour of Sass and Compass

What is sass?

Remember when you first heard of haml combining the dreaded semantic indentation of Python and the use of gratuitous punctation from Perl (thanks to Giles Bowkett for the description) to create a very cool and useful markup language. Well sass is the brain child from the same guy.

What follows is yet another quick introduction of Sass (I should have instead just linked to the doc but it’s too late…)

Example of sass code:

#foo
  :font-width 1em
  :border 1px solid
  :padding
    left  10px
    right 5px
  a
    :text-decoration none

which compiles down to the following CSS

#foo { font-width: 1em; border: 1px solid; padding-left: 10px; padding-right: 5px; }
#foo a {text-decoration: none;}

So like with Haml, Sass gets rid of redundant markup (like the braces and ;) and instead uses semantic indentation to distinguish rules.

Variables in Sass

But there is more, Sass also support variables:

!success_color = #7fb236
.success
  :color= !success_color
.success_box
  :background-color=  !success_color

It’s an easy way to change colors in your layouts by just changing the value of the variable. Magic numbers have long been a code smell when programming, why shouldn’t it be the same with CSS?

Mixins and Sass

Sass has a nice thing called mixins. Instead of copying and pasting some CSS code you always find yourself using, you can just use a mixin that will define this code to be reused later.

!border_highlight_color= #efefef
=message_box
  :border= 2px solid !border_highlight_color
  :padding 20px
  
.success
  +message_box
  :color= !success_color

will compile to

.success {
  border: 2px solid #efefef
  padding: 20px
  color: #7fb236
}

So now at last, you can keep your style sheets DRY, no need to hang them outside in the sun… (sorry for the lame attempt of humor, no need to throw tomatoes, it won’t happen again)

UPDATE: As said in the comment below by beejamin, the example is rather contrived and in this case it would make more sense to just add a message_box class to the element. A more complex and less contrived mixin example, with parameters is the mixin to layout list horizontally from Compass

=horizontal-list(!padding = 4px)
  +reset-box-model
  +clearfix
  li
    +no-bullet
    :white-space nowrap
    :float left
    :padding
      :left= !padding
      :right= !padding
    &.first
      :padding-left 0px
    &.last
      :padding-right 0px

Sass and Script functions

Sass has a few built-in functions allowing you to do things like this:

  .menu_bar
    :background-color= hsl(66, 6, 82)
    :width= abs(20px * -4)

will compile to

.menu_bar_color {
  background-color: #d3d4ce;
  width: 80px; }

It’s easy to add new functions by monkey patching the Sass:Scripts::Functions module. For example see this gist where I added functions to determine the height and width of an image.

Wrapping it up, a cool example of Sass

UPDATE: I decided to add this section to better show the power of using mixins and functions in Sass (this uses the height function as explained above that you can find in this gist)

One technique that is often used to speed up load time is to use CSS sprites. I usually use this mixin to do it:

=vertical_background_sprite(!img, !n, !total)
  !sprite_height= height(!img)/!total
  :background= transparent url(!img) 0 (!sprite_height * -(!n - 1)) no-repeat
  :height= !sprite_height
  
#new_pick
  +vertical_background_sprite(/images/item_info_icons.png, 1, 5)
#new_favorite
  +vertical_background_sprite(/images/item_info_icons.png, 2, 5)
#tell_friend
  +vertical_background_sprite(/images/item_info_icons.png, 3, 5)
#share_link
  +vertical_background_sprite(/images/item_info_icons.png, 4, 5)
#report
  +vertical_background_sprite(/images/item_info_icons.png, 5, 5)

Like this, I don’t need to hardcode the exact size of the sprites I have in my image.

For a programmer like me, Sass is a godsend, it makes my CSS code dry, more readable and make it feel more like a real programming language. Of course, the big problem is finding a designer that understands Sass…

Compass

Compass is a meta framework for Sass, it uses the power of Sass’s mixins to allow you to use frameworks like BluePrint, YUI without having the semantic classes nightmare of having all your classes named barbaric names like span-1, prepend-5.

I’m going to use the BluePrint library from compass as an example because that’s what I use in my project.

In a nutshell BluePrint is a CSS framework that gives you grid that is by default 950px with 24 columns 30 px each separated by a 10px gutter space. (all of this is customizable through the !blueprint_grid_columns, !blueprint_grid_width and !blueprint_grid_margin variables).
Compass provides mixins to make it easy to use the BluePrint grid.

So if you have a div with an id of sidebar, you can do this

#sidebar
  +column(5)
  +prepend(1)

This will make the #sidebar div be 5 columns wide, with one empty column behind it on the left. It will compile to the following CSS code:

#sidebar {
  float: left;
  width: 190px;
  margin-right: 10px;
  padding-left: 40px; }

For those who need a fluid layout, there is blueprint/modules/liquid.sass that provides a liquid layout.

I find it very easy to use the Compass BluePrint mixins for layout and it brings me the flexibility of CSS (easy to adapt the design to say an iphone without changing the html markup, quicker to load in browsers,…) while still having a very simple and quick way to style my page exactly as I want it to be.

For more information on Compass and some good primers, visit the blog of its creator and the Compass wiki on GitHub

Concrete Example of using Compass and Sass for creating a layout that people generally use tables for

UPDATE: After rereading this article, I thought that maybe I should show an example of Compass in action

Say you want to create a four column layout

For this in Sass (using Compass) you can do this:

  @import blueprint.sass

  body
    +blueprint-typography
    .container
      +container
  #header
    +column(24)
  #left_bar
    +column(7)
  #content
    +column(11)
  #fourth_column
    +column(1)
  #right_bar
    +column(5,last)

So you just define how many columns of the blueprint grid you need for each of your columns…

and use the following haml:

!!! Strict 
%html
  %head 
    %link{:rel => 'stylesheet', :type => 'text/css', :media => "screen", :href => '/css/four_columns.css'}
  %body
    .container
      #header
        %h1 Some nifty header
      #left_bar
        Left bar
      #content
        Lorem ipsum ad infinitum
      #fourth_column
        This is a 4th col  
      #right_bar
        Right bar

And you can see the result in all its glory here

If instead you want to use liquid layout, you just need to add @import blueprint/modules/liquid.sass

NB: Now I must confess that I never had to use a liquid layout in the projects I’ve been working on with Sass and Compass and just now when I tried it didn’t work (the last column fell off). After modifying the !blueprint_liquid_grid_margin to 0.4em it worked. I’ll ask on the mailing list about that and see how it goes…

I don’t know about you, but I find that this is at least as simple as using a table layout and the html code is cleaner too. Of course this could have been done with blueprint but in this case we have kept semantic names for the ids and classes. We do lose one thing from this technique though: it’s not easy to reorder the content without touching the markup (at least if we want to use the blueprint mixins)

For those thinking that using such a grid is not flexible, remember we’re using sass the size of the grid and number of column is defined by variables. So you can redefine the number of grid columns by setting !blueprint_grid_columns (or blueprint_liquid_grid_columns if you’re using the liquid layout), the width of each grid column with !blueprint_grid_width (or !blueprint_liquid_grid_width), and so on…

Don’t use CSS or table layouts, use Compass and Sass

So to conclude with why you should use Compass and Sass

Compass and Sass

  • allows you to make your layout code Dry
  • behaves like a programming language, so you can have fun refactoring your code
  • is easy to install and start with
  • takes care of the IE 6 incompatibilities by using the code from frameworks (I also use the excellent ie7-js library from Dean Edwards)
  • allows to easily design a grid based layout while still keeping semantic names

Now I don’t like spending a lot of time with a layout when I could spend some times on more productive things like the backend code or the javascript code of my website but Compass and Sass have considerably reduced the pain of having to make a website “pretty”. And compared to dealing with tables, I find the results much cleaner and maintainable.

I’m currently available for hire on a contract basis.

blog comments powered by Disqus