What are Compass, HAML, SASS, grids and Formtastic?

Beginning with our next release, our Facebook application will use Compass to tie together our 960.gs grid system, HAML and SASS code. It's important that open source developers working with us know how these technologies work together:

Grid System: (http://960.gs) Its very clean, does the job well and is highly flexible with what kind of page grids you can create. You can read more at http://960.gs They have a number of good examples and tutorials located there. They also have a package you can download that has a number of templates, such as a photoshop psd with a grid layout, so you can create photoshop designs specifically for use with the grid system. That package is available here: http://github.com/nathansmith/960-Grid-System/zipball/master

CSS: -CSS reset, 960.gs provides us with a good css reset, so that we have an equivalent blank slate to start with in all browsers. -Sass: (http://sass-lang.com/) Sass is a wrapper language for CSS that provides a lot of cool features such as variable style definitions, style expressions, improved readability and it works great with the other tools we will be using as you will see later. One interesting aspect of using SASS, is that you must convert your Sass files into CSS. It comes with two
programs css2sass (and sass) that will convert existing CSS into a Sass file, or vice versa. We are also using tools to automate this process.

HTML: -Haml: (http://haml-lang.com/) The same people who made Sass, also made something called Haml, which is similar in principle to Sass. It makes dynamic html substantially more readable and compact. Just to give you an idea of what haml looks like,
Here is the full piece of code for building the stories box on the main page. Also, in this sample, you will see a lot of things like t('.stories_title') that is for our localization code. That means translate the text for the stories title into the
current locale, such as english or french or spanish or pirate.

.panel_1
  .panelBar.clearfix
    %h2= t('.stories_title')
  .subtitle
    %span= t('.stories_subtitle')
  .storyList
    .list_stories.clearfix
      %ul
        - @contents.each do |content|
          %li
            .thumb
              - if content.content_image.present?
                %img{:alt => "story image", :src => content.content_image.url}
            .storyBlockWrap
              %p.storyHead= link_to content.title, story_path(content)
              %p.storyCaption= linked_story_caption content
              .profilePic= local_linked_profile_pic content.user
              .storyBlockMeta
                %p= t('.stories_posted_by', :fb_name =>
local_linked_profile_name(content.user), :date =>
time_ago_in_words(content.created_at))
                %p
                  %span.btn_left== #{link_to t('.stories_like'),
like_story_path(content.id), :class => "voteLink"}
#{content.votes.size}
                  %span.btn_mid== #{link_to t('.stories_comments'),
story_path(content, :anchor => "commentListTop")}
#{content.comments_count}
                  %span.btn_right= t('.stories_share')

The original code to generate that was hundreds of lines spanning multiple template files and requiring several libraries to generate. Haml makes heavy use of css style selectors for element declaration. This makes it much more natural and clear when interacting with css. Furthermore, we are using jQuery on the web interface, which also uses css style selectors to grab elements on the page. The combination of these three tools makes it very simple, standardized and concise to interact with elements on the page.

PUTTING THIS ALL TOGETHER: To facilitate combining grids and Sass and Haml, we are using a platform called compass. This is a tool facilitating a simple combination of grid systems and style sheets, while providing you with a good interface for
combining Sass mixin plugins and Sass variable declarations to create elegant and highly reusable layouts and designs.

The compass main website is here: http://compass-style.org/ The github page for compass has a great (although slightly verbose) introductory video that I highly recommend checking out. That can be found here: http://wiki.github.com/chriseppstein/compass (RECOMMENDED)

There is also a lot more documentation at that github link. Here is a link to the Sass mixins I was talking about: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixins There is a plugin for using 960.gs with compass located
here: http://github.com/chriseppstein/compass-960-plugin On that plugin page for 960, they have a great example showing how concise your grid declarations can become:

#wrap
 +grid-container
 #left-nav
   +alpha
   +grid(5,16)
 #main-content
   +grid-prefix(1,16)
   +grid(10, 16)
   +omega

As you can see, compass gives you very convenient helpers for defining grid column width on particular divs which is very beneficial. When you look at 960.gs initially, you can see it tends to require a fair amount of declaration of classes for the
elements, you have to give it a particular class for what column it starts on, where it goes to, etc etc, however with the compass plugin, you don't need to add any additional ids or classes rather than what is required to distinguish the elements.
Everything else can be done easily outside of the html structure in compass.

BOXES AND STANDARD ELEMENT STRUCTURE: A large portion of the elements in this app are very similar in structure. They have a border, and a top bar with a title, maybe a link, maybe a blurb, maybe some nav links, and then the content. While there will be differences in a number of the elements, I think that there is a great opportunity to use Sass mixins and compass functionality to greatly simplify the overall structure, so that you can identify the similarities of elements and only have to focus on building out the differences.

CRAZY FORM ELEMENTS HTML: We are using a rails plugin called formtastic (http://github.com/justinfrench/formtastic) which greatly simplifies the creation of forms and allows to do really cool things with nested objects and building forms that easily span multiple database tables. Furthermore, formtastic ties in directly with the internationalization settings we are using so that it will automatically pull the appropriate labels and button texts depending on your current locale. I am pointing this out because formtastic uses a somewhat unique setup with each input being in an LI element inside an OL inside a FIELDSET so I wanted to give you guys an example. Here is the code to generate the post story form and the generated code including the appropriate localization:

- semantic_form_for @story do |form|
  - form.inputs do
    = form.input :url
    = form.input :title
    = form.input :image_url
    = form.input :caption
  - form.buttons do
    = form.commit_button

produces:

<form action="/en/stories" class="formtastic content" id="new_content" method="post">
    <fieldset class="inputs">
        <ol>
            <li class="string required" id="content_url_input">
                <label for="content_url">
                    Url
                    <abbr title="required">*</abbr>
                </label>
                <input id="content_url" maxlength="255"
name="content[url]" size="50" type="text" value="" />
            </li>
            <li class="string required" id="content_title_input">
                <label for="content_title">
                    Title
                    <abbr title="required">*</abbr>
                </label>
                <input id="content_title" maxlength="255"
name="content[title]" size="50" type="text" value="" />
            </li>
            <li class="string required" id="content_image_url_input">
                <label for="content_image_url">
                    Image url
                    <abbr title="required">*</abbr>
                </label>
                <input id="content_image_url"
name="content[image_url]" size="50" type="text" />
            </li>
            <li class="text required" id="content_caption_input">
                <label for="content_caption">
                    Caption
                    <abbr title="required">*</abbr>
                </label>
                <textarea cols="40" id="content_caption"
name="content[caption]" rows="20"></textarea>
            </li>
        </ol>
    </fieldset>
    <fieldset class="buttons">
        <ol>
            <li class="commit">
                <input class="create" id="content_submit"
name="commit" type="submit" value="Post Story" />
            </li>
        </ol>
    </fieldset>
</form>