The Software Simpleton

Nomadic cattle rustler and inventor of the electric lasso

Backbone.js - Lessons Learned

I have been using Backbone.js for a few months now and I have found the learning curve to be a steep one. As is the case with any flexible framework, there are a number of ways of doing anything in Backbone.js and I think the framework could do with some tightening up to stop users having to roll their own custom implementations for common scenarios such as disposing of views.

For those that have been sleeping under a rock recently, Backbone.js is a client side MVC framework that should not require any introduction. The client side MVC framework seems to be a bit of a du jour thing at the moment but I think it is important to have some sort of organisational structure around JavaScript or the looseness of the language can quickly turn any javascript code into the now infamous ball of mud. Backbone.js is one way of achieving such a conformity.

The point of this post is to solidify where my current thinking is with Backbone.js and to welcome any comments from my readership of 10 or so readers that might point me to a better and brighter land. I must also warn you that I will be using coffeescript for the code examples instead of pure javascript and if this offends, please read no further.

Scenario

The scenario I want to illustrate is a simple one, I want to show how I transition from the state outlined below were a user selects from a list of what are called in the application context, business units: To a more detailed report illustrated in the image below: The user can go back and forward between these views and drill down into further views of the information but I want to concentrate on this simple scenario outlined above in the two screenshots.

Gotcha 1 - Don’t Have Views That Reference Each Other a.k.a. Coupling

In the scenario I have listed, I need some way to gather the user’s checkbox selection and pass these values to another view that renders the table and chart of results. My first few attempts at this in other applications was to let one of the views hold a reference to another and pass the information that way. An example of this type of naive implementation might look something like this:

You can see on lines 12 and 14 that I am creating a new view and calling render on it directly as a reference. This felt very wrong as there is now a coupling between the views. Thankfully somebody on twitter kindly pointed me in the direction of this post from Derek Bailey who is a wealth of information on Backbone.js.

The post outlines an alternative to creating and coupling one view in another like in the example above with the ManagementReportView. We instead create a central object that manages the raising of events and the subscribers for those events. Martin Fowler calls this the Event Aggregator pattern. This serves the purpose of decoupling the views from each other. The entire listing of the event aggregator is on line 3 of the following gist:

We are taking advantage of the way Backbone already handles events. The Backbone Events object is a module that can be mixed in with any object, giving the object the ability to bind and trigger custom named events. On lines 4 and 5, we are making sure that any of the views that want to publish or subscribe to events have a reference to the vent object. With this in place, I can simply raise an event from the BusinessUnitView and pass the newly created collection as an event argument. Below is the BusinessUnitView refactored to take advantage of the event aggregator:

The first addition is on line 3 where the view obtains a reference to our extended Backbone.js Events object and on line 20 where the custom Events object is used to trigger a custom event that is uniquely identified by a string. We are using the convention of a colon separated string (reportingbusinessunitview:load) to namespace the events and avoid collisions. Below is the code listing for the ManagementReportView that subscribes to the event listed above:

On line 3 of the above gist, we are using the bind method of the Events object to specify a callback that will be triggered when the event is raised and any optional arguments can be passed to the callback which in this instance is the newly created businessunits backbone collection that we created from the user input in the previous view. On line 7 we define the callback event handler. The load callback on line 7 is declared using the fat arrow => syntax. Coffeescript will take care of binding methods to this if you declare a function using the fat arrow => instead of the skinny one ->. This means you don’t need to use the underscore _.bindAll method as I would in javascript which can be quite tedious and relies on your diligence. One of the many reasons why you should be using coffeescript. On line 8 of the load callback we are setting the view’s collections reference to the argument raised from the triggered event and line 9 brings us to our next gotcha:

Gotcha 2 - Handle Backbone Model Events and not DOM Events Wherever Possible

Part of my reason for warming to backbone is that it brings conformity and organisation to my JavaScript/Coffeescript. It is all too easy for traditional browser based javascript to descend into a sea of DOM event handlers. Wherever possible, I have my views respond to backbone model or collection events. On line 9 of the above gist, I am adding an event handler to the reset event which is fired whenever a backbone collection is replaced with a bulk insert. On line 10 we are calling the built in fetch method of the backbone collection to retrieve the data from the remote server. When the data returns successfully from the remote server, the reset event is fired and we have bound the render event as a callback to this event on line 16. You can subscribe to events that are fired whenever elements are added or removed from a collection or when an individual model’s attributes change and you should get accustomed to all of these behaviours. Retrieving the data from the remote server brings me to gotcha 3 and in effect the render method:

Gotcha 3 - SRP - Keep Your Views Skinny

It is all to easy to end up with bloated views that do way to much and my first few attempts at backbone suffered from this. I’ve seen code that make calls to the remote server in the view and this is wrong. Let the collection/model do the remote call and subscribe to an appropriate backbone collection/model event. Below is the listing of the BusinessUnits object:

As this is javascript (coffeescript really) we can override any of the built in backbone collection methods like I am doing with the url method on line 6 but you can if required override fetch or parse methods for tighter control.

It is worth noting that the render method creates further subviews to attach to the parent view’s element. When refactoring backbone code, you tend to split your views up into finer detail or subviews to further inforce SRP.

The inner workings of the render method brings me to my last and most troublesome gotcha.

Gotcha 4 - Kill All Your Zombies…..Dead

I cannot take the credit for the excellent zombie analogy or in fact any of the revelations in this post, this again goes to Derek Bailey and a combination of this post and this Stackoverflow question and answer session. I have combined the contents of the above 2 links into how I now handle this common scenario.

If we refer back to the screenshot I showed at the start: I want to render a subview for every row in the above screenshot that has a cross or a tick image in the table columns. The gotcha outlined here is that I need to dispose of these views whenever the Back button on the top right is clicked. If I don’t dispose of the subviews, new and additional subviews will be added every time the user transitions to this view with a new collection selection. Multiple event handlers and general round chaos will occur and I have been there and it can be distressing to the uninitiated. There will be a number of views that are not attached to any element floating about in memory which gives them their zombie status.

Let us take a look again at the render method:

render: =>
  self = @

  @collection.each (item, counter) ->
    self.renderView(self.el, 'append', new ReportBusinessUnitView(model: item, vent: self.vent))

Here we are simply iterating over our collection and appending onto this view’s element a new subview for each element of the collection. We are actually calling a method named renderView of our own BaseView class that extends the Backbone.View class. More on that later but for completeness, below is the ReportBusinessUnitView class:

I’ve also found underscore’s templating to be much faster than JQuery’s templating engine which I initially started out using. Below is the underscore template:

The code will take care of iterating over our collection and attaching the subviews to our parent view. But if the user pressed back and then chose another selection and transitioned to this view again, we would add further subviews to this parent view. We need some way of keeping track of and disposing of our subviews.

To get round this problem, we have defined our own base class that uses underscore’s extend method to mixin additional functionality with that of the Backbone.Collection class by adding custom methods onto the Backbone.Collections prototype.

On line 7, we are defining a method named renderView which takes a jquery wrapped DOM element, a string denoting a function of the JQuery object to call and a backbone view. On line 8, we use javascript’s ability to reference and call a method on an object like accessing a hashtable. This string will generally be something like ‘append’ or a means of attaching the subview to the DOM. On line 9 we intialise an array to hold the subviews if it has not already been initailised using coffeescript’s ruby like ||= operator. Finally we push the newly created view onto the array.

We call the method like this:

@collection.each (item, counter) ->
    self.renderView(self.el, 'append', new ReportBusinessUnitView(model: item, vent: self.vent))

We pass the view’s element, the string ‘append’ which will be called on the jquery object in the renderView method like this $.fn[func].call and the subview we want attached. This is very neat and I can take absolutely no credit for writing it. We now have a store of all the views that are added.

All that remains is a means of disposing of these views and below are the two methods that take care of this on our custom BaseView class:

We can either call dispose on line 8 that will remove all subviews and the view itself or disposeViews on line 14 that will only remove the subviews. Dispose takes care of not only unbinding any event handlers but also of removing the element from the DOM. We can simply call one of these methods in an appropriate place on the view like this:

@disposeViews()

This has made backbone much more manageable although I cannot claim credit for much of the code.

That is it for this post and I will be amazed if anyone has made it this far. Please feel free to leave any comments. Below is the full listing of the BaseView class:

Simple CSS3 Login Form Using SASS

Previous Posts

I have been using these posts to cement the knowledge I am gleaning while transforming the markup for a product I am building. I find that trying to transmit the knowledge via blogging is the only way to really learn something or else it is easily forgotten. In the last three posts I have gone from defining my project file structure to creating the markup and CSS3 (with the extreme help of sass) for the header element in the image below. In this post, I want to outline the steps I took to create the following login page:

In the past, I hate to admit that I would have used a table to align the inputs with their labels but this time round I want to use css to control the layout. With that said, below is the haml that generates the markup for the above login form:

The above haml generates the following markup:

The only points of interest in the above markup are the new HTML5 attributes that are attached to the input elements on lines 8 and 10 of the above gist. These attributes are:

  • The required attribute which as you might have correctly deduced is used to specify that the element requires user input. Some browsers will alter the default appearance of required elements with a red border for example and most should stop you submitting the form if the mandatory field is left blank. It is worth remembering that this is HTML5, things can and will change until ratification.
  • The placeholder attribute which if set will place default text in an input field if the input element is empty or not in focus.

With the markup out of the way, we can now concentrate on some of the new CSS3 bells and whistles that I have used via sass and compass to create some of the nice effects in the form.

First of all, I want to concentrate on the login form itself: Below is the sass that is used to create the sunken effect for the text of the header and label elements that are outlined in the above image.

On line 1, is the definition of a mixin that I have used to avoid duplication in the two css selectors that assign styles to the <h2> and <label> elements. The mixin is used on lines 6 and 12 via the @include directive.
On line 3 of the above gist, I am using the new css3 text-shadow property that does what it says on the tin and adds a shadow effect to the text of a block element to make it stand out more.

It is worth noting that I keep all my colour variable definitions in a separate sass partial file named _colors.sass. This allows me to change the colour scheme in one file and not have to jump around the project files looking for the definitions. Below is an excerpt from colors.sass that shows the variable declarations used in the above gist:

$label-color: #445668
$label-box-shadow: #f2f2f2

The form element of the log in page uses a few of the new css3 techniques to add the new and now infamous css3 border-radius property that gives the form the nice rounded corners effect. It is often jokingly stated that the main purpose of CSS3 is to facilitate the adding of rounded corners to block elements.

But first of all, I want to show how I got this rippled effect on the bottom of the form: I have used the new css3 box-shadow property to achieve this effect. As the name suggests, the box-shadow property is used to apply an inset or drop shadow to a block element. It is also possible to add multiple box-shadows to an element as in this example. As this is a css3 experimental property there are the usual vendor specific prefixes for this property….that is unless you use compass and you can use the box-shadow mixin like I am below:

#new_user_session
  @include box-shadow($login-box-shadow-color 0 0 2px, $login-box-shadow-color 0 1px 1px, #fff 0 3px 0, $login-box-shadow-color 0 4px 0, #fff 0 6px 0, $login-box-shadow-color 0 7px 0)

I am passing in alternating box-shadow colour definitions to the mixin that are delimited by commas to give the appearance of a ripple. The above sass generates the following css:

#new_user_session {
  -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 0 2px, rgba(0, 0, 0, 0.2) 0 1px 1px, white 0 3px 0, rgba(0, 0, 0, 0.2) 0 4px 0, white 0 6px 0, rgba(0, 0, 0, 0.2) 0 7px 0;
  -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 0 2px, rgba(0, 0, 0, 0.2) 0 1px 1px, white 0 3px 0, rgba(0, 0, 0, 0.2) 0 4px 0, white 0 6px 0, rgba(0, 0, 0, 0.2) 0 7px 0;
  -o-box-shadow: rgba(0, 0, 0, 0.2) 0 0 2px, rgba(0, 0, 0, 0.2) 0 1px 1px, white 0 3px 0, rgba(0, 0, 0, 0.2) 0 4px 0, white 0 6px 0, rgba(0, 0, 0, 0.2) 0 7px 0;
  box-shadow: rgba(0, 0, 0, 0.2) 0 0 2px, rgba(0, 0, 0, 0.2) 0 1px 1px, white 0 3px 0, rgba(0, 0, 0, 0.2) 0 4px 0, white 0 6px 0, rgba(0, 0, 0, 0.2) 0 7px 0;
}

The above css creates the rippled effect.

Now let us get back to those nice rounded corners that are this season’s black in the fashionable world of css3: The css3 border-radius property is used to give a block element rounded corners and as we cannot be bothered to type all these vendor specific prefixed properties, we are going to use the compass border-radius mixin. Below is the border-radius mixin applied to the login form element:

#new_user_session
  @include border-radius(10px)

Which generates the following css:

#new_user_session{
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
-khtml-border-radius: 10px;
border-radius: 10px;
}

As you can see, compass takes care of the vendor specific pain.

Below is the sass in its entirety that is employed to create the css styling effects of the form minus the inputs.

The only point that I have not covered is the gradient effect that is created using the compass border mixin on line 6 of the above gist. I described linear gradients in the previous post.

Input Styling

I have used a combination of all the techniques mentioned so far to add some definition to the input elements: Below is the sass that is used to create the box-shadow, linear-gradient and border radius effects:

CSS3 Transitions

With CSS3 you can now achieve some effects that would have in the past required javascript to achieve. One of these techniques is known as a css3 transition. This allows the author to specify a css change or transition from one css style to another. It is also possible to put a time delay on the transition.

This is impossible to show without a demo and as my site is not on a public facing server yet, so I am going to have to point to these examples.

In my log in page, I am specifying that I want the text input’s border and background to change when the cursor is hovered over the input control: We can also put a delay on the transition which equates to a tasteful delay of a specified time before the transition occurs.

Below is the sass I have used to create this nice time delayed transition:

I am using the compass transition-property and transition-duration mixins to produce this effect. The compass documentation for the transition mixins can be found here.

Button Effect

Lastly I want to describe how the styling was created for the button: I have used the fancy-buttons library to easily create this effect.

With the library imported, I can simply use the fancy-button mixin to generate the css3 styles like this:

input[type=submit]
  @include fancy-button(#617798, 14px, 1em, 4px)
  width: auto
  text-transform: uppercase

I will leave things here for this article, if you made it to the end of the article then pat yourself on the back!

Creating Gradients With Compass and SASS

Previous Posts

In the previous two posts, I have started to outline the transition of my yet to be completed product from old school xhtml, css and javascript into the new world of HTML5 and CSS3. As the product is not even on the market yet, I am taking the bold step of tackling the design myself. I am a css and design heretic so this is quite a difficult step for me. On the plus side, I will learn a lot on the way no matter what the outcome is. In this article, I want to touch on creating gradients with sass and compass.

A gradient in the context of css is a gradual transition between two colours. This transition can be transformed through a vertical axis or a horizontal axis. Below is how my application looks after I have applied the styles that I will create in this article.
I have applied gradients to both the header section and the navigation bar of the html document. CSS3 comes with a gradient property and most of the modern browsers have their own prefixed slants on this property. As we are using compass and sass, we can forget about the need to create these vendor specific duplicated linear-gradient properties. Yet another reason for using compass is that compass will output the vendor specific cross browser rules. The latest version of compass has the excellent images module and I am going to take advantage of the background-image mixin to create the gradient effect. Below is the rule that will be applied to the new html5 <header> element of our document:

body > header
  background-color: $header-bg
  @include background-image(image-url('noise.png'), linear-gradient(darken($header-bg, 20), $header-bg, lighten($header-bg, 11)))

I am using the background-image mixin to generate the linear-gradient as recommended in the latest compass docs changelog which states:

The linear-gradient and radial-gradient mixins have been deprecated. Instead use the background-image mixin and pass it a gradient function. The deprecation warning will print out the correct call for you to use.

We are also passing in a fallback image if the browser does not support linear-gradient.

For IE6 and IE7 there is the filter-gradient mixin. I will probably create an IE < 8 conditional stylesheet and try this out at a later stage.

It is also worth noting that we are taking advantage of the sass functions lighten and darken to avoid having multiple colour hex values to change. The above background-image mixin will generate the following css:

/* line 1, /Users/paulcowan/projects/leadcapturer/app/assets/stylesheets/partials/_header.sass */
body > header {
  background-color: #6a85af;
  background-image: url(/assets/noise.png), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #acbbd3), color-stop(50%, #6a85af), color-stop(100%, #4f6992));
  background-image: url(/assets/noise.png), -webkit-linear-gradient(#acbbd3, #6a85af, #4f6992);
  background-image: url(/assets/noise.png), -moz-linear-gradient(#acbbd3, #6a85af, #4f6992);
  background-image: url(/assets/noise.png), -o-linear-gradient(#acbbd3, #6a85af, #4f6992);
  background-image: url(/assets/noise.png), -ms-linear-gradient(#acbbd3, #6a85af, #4f6992);
  background-image: url(/assets/noise.png), linear-gradient(#acbbd3, #6a85af, #4f6992);
}

I hope you can see the projection of one line of vendor independent compass/sass code to the many lines of browser/vendor specific css code.

Navigation Bar

We will use the same technique to apply a gradient to the navigation bar: We are going to use the new semantic <nav> element of html5 to mark up the navigation and then apply css rules to it. Below is the haml for the new navigation bar:

And here is the rendered output of the above haml

<nav role="navigation">
    <ul role="user">
      <li>
        <a href="/logout">log Out</a>
      </li>
    </ul>
    <ul role="main-navigation">
      <li>
        <a href="/Home/Index" data-method="get">Capture</a>
      </li>
      <li>
        <a href="/Archive/Index" data-method="get">Archives</a>
      </li>
    </ul>
</nav>

I am also using the new html5 semantic role attribute. HTML5 has many of these new semantic markers that help devices such as screen readers pick out the relevant sections.

I want to take this opportunity to show the power of both sass variables and the extremely useful sass functions desaturate, darken and lighten to DRY up your css. Below are the variable declarations we will be using for the navigation bar:

Only on line 1 do we actually specify any hex value for a variable, in the subsequent variable declarations, we pass in relevant percentage values to the lighten and darken functions to keep everything in ratio. A change to the $nav-bg variable will cause the other variables to adjust accordingly.

A full list of similar sass colour functions can be found here.

Below is the listing for the _navigation.sass partial file that contains the rules for the <nav> tag outlined above:

Besides the background-image mixin on line 4 that I described previously, we are taking advantage of a couple of other useful sass mixins:

  • Horizontal List (line 11): which transforms a <ul> list horizontally.
  • link-colors (line 20): Which sets the colors for a link in one mixin.

I will leave things here for this post but in the next post I will describe the layout I am going to use for the main section of the page. I had previously used the compass blueprint library which is a css grid layout framework but the world has moved on and I am going to see what else is available. If anyone can recommend a more modern approach please leave a comment below.

Please leave any comments below. Feedback is always appreciated.

Site Refresh With HTML5 and SASS - Part 2

Previous Posts

In the last post I took a walk through the basic set up of my sass files that I will be using for the update of my site to the new landscape of html5.

Below is the file layout for my sass files: I went on to mention that the application.css.sass file above is used as a manifest and I just use it to point to my application point of entry screen.sass.

application.css.sass looks like this:

@import "screen"

screen.sass currently looks like this:

In the last post, I explained how the reset mixins in lines 2 and 3 provide a facility for removing browser inconsistencies by a mechanism known as css reset rules. I now want to explain the contents of the other files that are imported via the sass @import directive.

SASS Partials

All the files that are imported on lines 5 to 12 of screen.sass are sass partials. Any sass file that is imported as part of a parent or main css file and does not need its own individual css file is what is known as a partial. A sass partial file does not make sense on its own. In this example, screen.sass will generate one css file that is made up of seven partials. This is very analgous to rails partials or any partial in any mvc framework. The convention for a sass partial is to begin the filename with a _ character. If you refer to the opening image, each file in the partials directory begins with an underscore. This tells sass not to generate an individual css file for the partial and only use it for imports. To confuse matters, you drop both the _ and the file extension in the @import statement.

The first import statement on line 5 imports a currently empty file named _utilities.sass. This file will be used for housing any reusable mixins or sass functions that we create on our journey to market. Next up we have the partial _colors.sass.

SASS Variables

_colors.sass currently looks like this:

The point of _colors.sass is to have a central location were we can adjust the colour scheme of the website. The explicit colour values that will be referenced in other sass files for things like background colours etc. are stored in what are known as sass variables.

One of the glaring misses in CSS is the ability to store reusable values in variables. This can lead you to having to use potentially faulty search and replace techniques in your text editor to swap hex code values and manage colour palette changes in your stylesheets. With sass you can assign values to variables, and manage colours, border sizes etc. in a single location.

SASS variables start with the $ character and can contain any character that is valid in a CSS class name. In line 1 of _colors.sass, I am storing the hex value of the colour that I will use for the header section of my page. As colors.sass is imported in screen.sass, the variables that are declared in _colors.sass will be available in any partials that are imported in screen.sass. Below is an example of how the sass variable can be used:

body > header
  background: $header-bg

Line 3 of _colors.sass contains the following variable declaration:

$subtitle-color: lighten($header-bg, 58)

The return value of the lighten function that is outlined above is used to assign the value of the $subtitle-color variable and is one of the many utility functions that are included in SASS. The lighten function unsurprisingly lightens the colour by a percentage value. In the above example, we can tie the $subtitle-color variable to the $header-bg variable so they will always be in ratio. A quick look at the sass docs will broaden your knowledge of what sass functions are available.

Before carrying on, below is the rendered HTML from our main application.html.haml file which we will be applying css rules to:

Typography

The next sass partial file that we are importing from the parent screen.sass is the _typography.sass file, which currently looks like this:

This file as the file name suggests is where all the type face instructions will be centrally held. On line 1 of _typography.sass, we are declaring a css class with a name of heading and then declaring the font-family we want to use and the fall back options. It is unlikely you will have heard of the Orbitron font-family and that is because we are importing it from the Google Web Fonts API. I mentioned this in the previous post. We can import fonts from the google web fonts api by declaring a separate <link> element for each font we want to import. The declaration for importing the Orbitron font is below:

%link{:rel => "stylesheet", :type => "text/css", :href => "http://fonts.googleapis.com/css?family=Orbitron:regular,italic,bold,bolditalic"}

On line 4 of the typography.sass file, we are using the css selector body > header h1 to select the first h1 element of the new html5 header element. On line 7 of _typography.sass, @extend is used to tell sass that we want the body > header h1 selector to inherit all the styles defined in another selector. This is worth the sass price of admission alone. The ability to DRY up your css by inheriting other selector rules reduces repeating yourself tenfold. This is one of the many reasons why sass will (not should) become the new css.

In line 11 of _typography.sass we come across the first use of what is arguably sass’s most important feature which is known as a sass mixin. A mixin as the name suggests, mixes in rules into other rules. We extract the rules using the @mixin directive. For example we could create a mixin defined like below:

@mixin BigText
  font-size: 20px
  font-weight: bold
  text-transform: uppercase

We can mixin these rules into other rules using the @include directive.

body > header h1
  @include BigText

It is also possible to pass arguments to mixins just as is outlined in line 11 of typography where we are mixing in the rules of the compass Text-Shadow mixin. This mixin will create the rules for the new css3 text shadow property. The CSS3 text-shadow property has been around for some time now and is commonly used to recreate Photoshop’s Drop Shadow type shading to add subtle shadows which help add depth, dimension and to lift an element from the page.

@include text-shadow(rgba(#000, 0.8) 0 0 8px)

Below is a screenshot of what the some total of our css styling looks so far: I think you will agree that this looks pretty ugly but as we continue, I will progressively make it look better: As you can see, I am not a designer but this looks reasonable enough to me but probably less so to others. Ok, back to sass…

On line 18 of _typography.sass, we come across the strange syntax of #{headings()}. This helper function is part of the compass library. This helper function will emit all the h[n] headings for you. Below is the css that is rendered from this function:

.heading, body > header h1, h1, h2, h3, h4, h5, h6 {
  font-family: "Orbitron", "Georgia", "Helvetica Neue", Arial, San-Serif;
}

I am going to leave things here for now but in the next post I will outline some other cool sass techniques such as gradients.

Please feel free to leave comments below.

Site Refresh With HTML5 and SASS - Part 1

I have been working on this as a side project for some time now and I have decided to take a deep dive into what is available in HTML5 and CSS3 and update the front end code. This yet to be birthed product is written in JRuby and is a rails application. I have recently been through the pain of upgrading to Rails 3.1 in order to take advantage of the dazzlingly new, shinny and controversial Rails 3.1 asset pipeline. I have been using sass and compass for some time and I had previously used the compass blueprint library for layout and utilities. This feels a bit dated now so it is high time to refresh. I have previously blogged about sass, compass and blueprint here.

I am trying to avoid dissolving into deep depressive rants about things and I could go off on one about the Rails 3.1 abstraction levels reaching their natural meltdown limits with this Rails release. It is not quite .NET webforms but it is certainly heading in that direction.

Markup Refresh

I am going to take this site refresh one blog post at a time. I want to be sure I remember my transitions.

The head is the only sensible place to start in HTML so here is my new header code which is written in your favourite mark up language and mine HAML:

The above is my main rails layout file. The following are the main points of interest:

  • In HAML the HTML declaration is a two pronged approach. You first of all place the doctype marker !!! in the .html.haml file:
!!!
 %head

Secondly, you need to tell HAML the output format on application start up which is specified in the main rails environment.rb file.

Haml::Template.options[:format] = :html5

With these options set, we can pass the rendering of the correct !DOCTYPE instruction to the HAML runtime. This generates the following HTML declaration:

<!DOCTYPE html>
  • On lines 3 and 5 of the gist, we are declaring the single application javascript and css declarations that are generated from the Rails 3.1 asset pipeline.

  • On lines 8 - 11 we are going to take advantage of the Google Web Fonts API and CSS3 to embed some nice looking fonts in the application. There is a separate declaration and import for each web font that the application will make use of. More on this in later posts.

  • On line 13 we encounter our first new HTML5 tag, the header element. The semantic header tag specifies an introduction, or a group of navigation elements for the document.

  • On line 14, the hgroup tag is used to group the document’s title and associated subtitles. The hgroup tag can only contain a group of h1 to h6 elements.

Below is the beautifully indented output of the HAML markup:

SASS Folder Structure

When I first started using SASS there was nowhere near the level of docs and blog posts available to the end user. As part of this site refresh, I took a look on github at some of the open source projects using SASS to find guidance on how some of the SASS officionados, use SASS.

It is also worth mentioning before proceeding that I use the possibly now old school and pythonesque sass syntax and not the more css like scss syntax. When I started with sass there was no scss syntax but to be honest, I think .scss was introduced to make sass more designer friendly. As a developer, I feel more at home with whitespace delimiting my blocks rather than the now horribly out of fashion curly braces.

The screenshot below outlines a popular file organisation pattern for structuring your SASS files:

The first point of entry is the application.css.sass file. Back in what are probably now classified as the old days, a separate process running the compass.exe would watch the sass directory for changes to your sass files. Any changes were compiled into your ~/public folder. With rails 3.1, we’re getting css and javascript served up through application.css and application.js. These main application files are really just manifest files that bundle everything in the stylesheets or javascripts folder into one file.

First Rails 3.1 SASS Gotcha

Out of the box, the application.css.sass file looks something like this:

/*
 * This is a manifest file that'll automatically include all the stylesheets available in this directory
 * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
 * the top of the compiled file, but it's generally better to create a new file per style scope.
 *= require_self
 *= require_tree . 
*/

The requite_tree statement above tells the system to bundle everything in the stylesheets folder into a single file via the magic of sprockets.

When I first started using this approach in Rails 3.1, I quickly found out that sass variables or indeed sass scopes were not shared across files. This is because application.css.sass is really for combining plain css files into one via the magic of sprockets. With sass files, you need to use the @import directive in the application.css.sass file to import additional sass files. If you are using application.css.scss with require_tree, the runtime will still compile your sass and combine the resultant css into one file but there will be no shared scopes for things like variables, mixins etc. It took me a while to figure that one out. Remember I mentioned the raised abstraction levels in Rails 3.1?

With that in mind, my application.css.sass file looks like this:

@import "screen"

The application.css.sass file is now just a pointer to the main application logic file, screen.sass.

At this time of writing, my screen.sass file currently looks like this:

On line 1 we are using the @import directive to import the compass library into our code. Using sass without compass is a complete waste of an incredible resource, compass has a wealth of useful features that are hard to ignore. If you are not using compass with sass, you might as well be using the less framework. Compass has a multitude of mixins, functions and other utilities that make css all of a sudden fun to a css heretic like me.

Lines 2 and 3 of screen.sass bring the output or generated styles of two of these compass mixins into the rendered application.css output via the sass @include directive. The @include directive takes the name of a mixin and optionally arguments to pass to it, and includes the styles defined by the mixin into the current rule. The following link has some examples that illustrate how they can be used.

Both these mixins generate what are known as css reset rules. Reset stylesheets try to reduce browser inconsistencies in things like default line heights, paddings, margins and font sizes. The goal of the reset stylesheet is to give you a completely style free starting point. For example some browsers indent unordered lists, others do not. The reset rules level the playing field and gives you a neutral cross browser starting point to add your own.

The first mixin, the global-reset mixin is based on Eric Myer’s 2.0 global reset rules.

The second mixin, the reset-html5 mixin, provides a basic set of HTML5 elements so they are rendered correctly in browsers that do not recognise them and reset in browsers that have default styles for them.

Below is the css that is produced from these mixins:

I think I prefer the 2 lines of sass code to the output above. There are a number of compass reset mixins that can be utilised in your code.

I think I will leave things here, in the next post I will reveal what is inside the other files in the above screen.sass file.

If you are a web developer and you are not using sass/compass, I have to ask the question….why?