Powerful Color Manipulation with Sass

Posted January 11, 2010

Update: After this post was written, Sass 2.4 was renumbered to Sass 3. The title and text have been updated accordingly.

There’s a lot of exciting stuff coming down the pipeline for Sass 31. I want to keep folks up-to-date on what they have to look forward to, so I’m starting a series of blog posts detailing the new features I’ve been working on.

New Color Functions

One of the new features I’m most excited about is a huge expansion in the color-manipulation capabilities of Sass. Sass has always supported arithmetic with colors, allowing them to be added, subtracted, and even multiplied. For example, #f00 + #00f = #f0f in Sass.

Unfortunately, beyond basic lightening and darkening, basic arithmetic isn’t a great fit for colors. That’s why Chris Eppstein pioneered a far more powerful approach in his Sass plugin. He used color theory and HSL colors to create Sass functions that can modify colors in a much more meaningful way.

Compass-colors has been merged into the Sass core for version 3. This means that Sass has a host of new functions for manipulating the HSL values of colors— whether the colors themselves are RGB or HSL. The most basic of these functions simply return the hue, saturation, or lightness components of the color:

hue(#cc3) => 60deg
saturation(#cc3) => 60%
lightness(#cc3) => 50%

There are also functions for changing components of the color while keeping the other components the same. These functions each add (or subtract) the given value from the appropriate component and return the resulting color:

adjust-hue(#cc3, 20deg) => #9c3
saturate(#cc3, 10%) => #d9d926
desaturate(#cc3, 10%) => #bfbf40
lighten(#cc3, 10%) => #d6d65c
darken(#cc3, 10%) => #a3a329

There are a few useful functions that, while easy to create using these functions, are nice to have:

grayscale(#cc3) => desaturate(#cc3, 100%) = #808080
complement(#cc3) => adjust-hue(#cc3, 180deg) = #33c

Finally, my favorite compass-color function is one that takes two colors and mixes them together, using the best approximation of mixing pigments we could come up with. It can also take a parameter indicating that more of one color or more of the other should be used:

mix(#cc3, #00f) => #e56619
mix(#cc3, #00f, 10%) => #f91405
mix(#cc3, #00f, 90%) => #d1b72d

These functions make it incredibly easy to choose one or two base colors and generate a theme of colors that all look great together. Check out some of Chris’s examples for inspiration.

Alpha Channel Support

A related feature for Sass 3 is full support for alpha channels in colors. In Sass 2.2, colors with alpha channels couldn’t use arithmetic and couldn’t be passed to functions that expected colors such as the ones above. In 3.0, not only will they work just like other colors, but they’ll have their own set of functions as well.

First, to create a color with an alpha channel, use rgba or hsla, just like in CSS. All color functions will preserve the alpha channel:

grayscale(rgba(51, 255, 51, 0.75)) => rgba(153, 153, 153, 0.75)
complement(rgba(51, 255, 51, 0.75)) => rgba(255, 51, 255, 0.75)

The mix function will even automatically weight translucent colors so that they have less of an effect on the resulting color2:

mix(rgba(51, 255, 51, 0.75), #f00) => rgba(178, 95, 19, 0.875)
mix(rgba(51, 255, 51, 0.90), #f00) => rgba(163, 114, 22, 0.95)

There’s also a function for getting the alpha channel of a color, as well as two for modifying it. Each of these functions has two names, but the effects are equivalent:

alpha(rgba(51, 255, 51, 0.75)) => 0.75
opacity(rgba(51, 255, 51, 0.75)) => 0.75

opacify(rgba(51, 255, 51, 0.75), 0.1) => rgba(51, 255, 51, 0.85)
fade-in(rgba(51, 255, 51, 0.75), 0.1) => rgba(51, 255, 51, 0.85)

transparentize(rgba(51, 255, 51, 0.75), 0.1) => rgba(51, 255, 51, 0.65)
fade-out(rgba(51, 255, 51, 0.75), 0.1) => rgba(51, 255, 51, 0.65)

Use It Now

The new color support is available in the master branch of the Sass repository right now. There are two options for using it. The easiest way is probably to install the haml-edge gem by running gem install haml-edge (if you’re using Rails, you’ll need to add config.gem "haml-edge" to config/environment.rb).

You can also install it as the haml gem by downloading it from GitHub and running rake install in the haml directory.

1 There’s cool stuff in the works for Haml, too, but the 3.0 release is going to focus mainly on Sass.

2 I stayed up until 6 AM one night figuring out a function for supporting the weight parameter to mix and the weighting via opacity at the same time. I dearly hope someone, somewhere uses them together.

Reid Young said January 11, 2010:

The first time I used Sass I remember thinking “this would really be a home run if it supported HSL manipulations”. Both of you have done fantastic work—thank you for sharing it!

Geoffrey Grosenbach said January 11, 2010:

I frequently do color math with Sass. This will fix some annoyances and make it even more powerful. Looking forward to it!

Eric Meyer said January 11, 2010:

This is absolutely fantastic, and will change my life forever. I love you boys.

Also: I promise to use the weight mixing parameter along with rgba alpha weighting. Anything for you.

Michael Bleigh said January 12, 2010:

This is a great addition, but just keeps me thinking: isn’t it time SASS got separated from HAML into its own project? It’s mature and robust enough that it’s not just a “me too” and I don’t particularly care for HAML but I love SASS. Are there any plans for such a split?

xmariachi said January 12, 2010:

Yep, great addition. I’m about to include Sass on my (first) ruby+haml project so good to know about this. BTW I knew it through the irc channel :)

Mason Wendell said January 12, 2010:

This is fantastic. I love all the new work that’s gone into this project. Totally changed how I work, and 100% for the better.

Nathan said January 12, 2010:

Michael: We’ve thought about this several times in the past, but there are some annoying logistical problems. First, there’s a lot of code shared between Haml and Sass. Second, Haml will always need to include Sass for backwards-compatibility.

We may yet do so, but I can’t say when with any surety. One thing that will likely happen sooner is a way of installing Sass without needing to interface directly with RubyGems at all.

RSL said January 13, 2010:

Good work on this you guys. Really, really good work. Cannot wait to play around with it.

Dira said October 30, 2010:

Great functionality!

I have used this for a CSS3 stylish button plugin – give a color code and you get a super yummy, gradient-ish button.

See it in action here

Make your comments snazzy with Textile!