Haml and Sass 3.1 are Released

Posted April 24, 2011

Nearly a year after the release of Haml and Sass 3, we’re ready to announce the release of Haml and Sass 3.1. You can install them now:

gem install haml
gem install sass

That’s right, there are two separate gems. last September, Haml and Sass are being split into two separate projects. They can now be installed and used completely separately. This split is long overdue; the details can be read in the original post.

As has been the case for a while, Haml is largely in maintenance mode; it has very few new features. The biggest change between Haml 3.0 and Haml 3.1 by far is the removal of Sass. For the rest of the changes you can read the Haml changelog.

Sass, on the other hand, has lots of exciting changes. The full coverage is given in the Sass changelog, but I’ll go over some of the most notable ones here.

User-Defined Functions

Sass has supported a wide variety of built-in functions for quite a while. However, until now, in order for a user to define their own Sass functions, they’d have to dive into the Ruby API. This was hardly ideal, especially when many of the functions users wanted to write were simple things to make some math less repetitive.

Sass 3.1 adds the ability for users to write their own functions within Sass itself. For example:

$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

This defined a grid-width function for calculating the width of grid cells. The value marked with @return is the result of the function. This function can be used anywhere a normal Sass function can.

Functions can also contain variable declarations and control directives like @if and @for.

Keyword Arguments

Mixins and Sass functions now support keyword arguments. This means that, instead of memorizing the order of arguments for each mixin and function (which is a pain especially for those that take many arguments), you can pass the arguments in in any order by naming them. For example, with a mixin:

@mixin border-radius($value, $moz: true, $webkit: true, $css3: true) {
  @if $moz { -moz-border-radius: $value }
  @if $webkit { -webkit-border-radius: $value }
  @if $css3 { border-radius: $value }
}

@include border-radius(10px, $webkit: false);

This sets the $webkit argument to true, while leaving the other arguments to their default values.

Keyword Color Functions

Keyword arguments allow a new sort of Sass function: those that behave differently depending on which keywords they’re given. There are two notable new functions that make use of this.

The adjust-color function adjusts the value of one or more properties of a color by a fixed amount. It works just like the old lighten, saturate, and adjust-hue functions, except it decides which properties to adjust based on keywords. So adjust-color($color, $lightness: 10%) increases the lightness of $color by 10%, just like lighten($color, 10%).

The scale-color function fills a need that wasn’t addressed by the old color functions. It works like adjust-color, but rather than adjusting properties by a fixed amount, it scales them fluidly by a percentage. The closer the percentage is to 100% (or -100%), the closer the new property value will be to its maximum (or minimum). For example, scale-color(hsl(120, 70, 80), $lightness: 50%) will change the lightness from 80% to 90%, because 90% is halfway between 80% and 100%. Similarly, scale-color(hsl(120, 70, 50), $lightness: 50%) will change the lightness from 50% to 75%.

Lists

CSS has always had a notion of lists. Any property that has a series of values, like 1px solid black or Helvetica, Arial, sans is a list. Sass now has built-in support for manipulating these lists, just like it already did for strings, numbers, and colors. You could already assign lists to variables or pass them to mixins; now Sass provides several useful functions for dealing with these lists:

  • The nth($list, $n) function returns the nth item in a list. For example, nth(1px 2px 10px, 2) returns the second item, 2px. Note that lists in Sass start at 1, not at 0 like they do in some other languages.
  • The join($list1, $list2) function joins two lists into one. For example, join(1px 2px, 10px 5px) returns 1px 2px 10px 5px.
  • The append($list, $val) function appends a single value to the end of a list. For example, append(1px 2px, 10px) returns 1px 2px 10px.
  • The length($list) function returns the length of a list. For example, length(1px 2px 10px 5px) returns 4.

@each

Sass 3.1 also adds the @each directive, which assigns a variable to each item in a list in turn, just like @for does for numbers. This is useful for writing a bunch of similar styles without having to go to the trouble of creating a mixin. For example:

@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}

is compiled to:

.puma-icon {
  background-image: url('/images/puma.png'); }
.sea-slug-icon {
  background-image: url('/images/sea-slug.png'); }
.egret-icon {
  background-image: url('/images/egret.png'); }
.salamander-icon {
  background-image: url('/images/salamander.png'); }

Up Next

Although I have a full time job now, and thus less time to work on Haml and Sass, we’ve still got plenty of cool stuff planned for version 3.2. Keep an eye out!

vjt said April 24, 2011:

Wonderful, thank you, sir. My Gemfile will be happy! :-)

PaBLoX said April 24, 2011:

Cool :), very useful addons btw.

Do you plan to include an easier way to modify the scss output? :P

Levi Figueira said April 24, 2011:

THAAAANK YOUUUU!!! :D

Gaurav Mishra said April 26, 2011:

Will surely evaluate this in whole. I am pretty new to this though.

Manuel Meurer said April 26, 2011:

So Sass is a programming language now? Sweet! :)

dogfood said April 28, 2011:

Just want to say: Thank you. Since starting with SASS last fall, my way of coding for CSS totally changed. SASS became one of my most used (and most fun) tools. Thank you.

Pete Forde said April 29, 2011:

So if you support @if macros, variables, lists, functions and includes… can we consider Sass to be Turing complete?

Nathan said April 29, 2011:

Yes, Sass is at long last actually Turing complete. You could, if you were sufficiently determined, write a Sass parser in Sass.

Frederick Townes said April 30, 2011:

Very exciting additions, looking forward to more!

nickf said June 14, 2011:

Hey, I’ve been looking for information about the requirements for running SASS. Do you know what version of Ruby is required?

Nathan said June 14, 2011:

Both require Ruby 1.8.7 or higher.

nickf said June 15, 2011:

Thanks for that!

Hes said June 28, 2011:

Hi there! I don’t know where to contact you about a bug. So I figured I’d just post it here. I’m just newly trying out SASS and I’m about to dive in, however, there seems to be something wrong with the scale-color function:

scale-color(#e0e4cc, $lightness: 25%) = #e8ebd9
scale-color(#e8ebd9, $lightness: 25%) = #eef0e3

What I need to do is this:

scale-color(scale-color(#e0e4cc, $lightness: 25%), $lightness: 25%)

but it gives me #eef0e2 and wrong values as I do it so forth recursively.

Nathan said June 28, 2011:

I think you’re hitting a minor rounding error. The HSL value that scale-color produces has to be rounded somewhat when converted to RGB. However, if it’s fed directly into another scale-color call (as opposed to copy-pasting the RGB value) it can use the original HSL values without any rounding errors. In any case, the minor difference in RGB value shouldn’t be noticable.

For future reference, bugs can be filed on the GitHub tracker.

Marc said July 17, 2011:

I just discovered your tool, thank you for your great work !

Tom said September 29, 2011:

Nice Work ! I think this change my css coding enormous. Will take a deeper look to SASS & HAML

Christian said October 13, 2011:

@Nathan: Please update the “Windows Installer” link on http://sass-lang.com/tutorial.html. Old is: http://rubyinstaller.org/download.html New should be: http://rubyinstaller.org/downloads/

Johannes said November 25, 2011:

The link to the binary-archives at rubyforge is linking to haml’s archives. The sass ones are located here: http://rubyforge.org/frs/?group_id=9702

simonleung said November 25, 2011:

Instead of @if $moz { -moz-border-radius: $value } @if $webkit { -webkit-border-radius: $value } @if $css3 { border-radius: $value } , using a “vendorPrefix()” function better, ie, @if $css3 { vendorPrefix()border-radius: $value } @if $css3 { border-radius: $value }

Gilles Gallico said December 26, 2011:

I’ve just discovered your tool. Seems really interesting. Thank you for that. Will use it and wait for additions.

cx said January 05, 2012:

how do i use css hack in scss?

when i try to convert a css file to a scss file ,sth wrong:

head_left{

float:left; width:420px; padding-top:7px; +vertical-align:middle;/css hack for ie7/ }

Error on line xx of (css): Invalid CSS after “padding-top:7px;”: expected “}”, was “+vertical-align…”

Make your comments snazzy with Textile!