Blog
Sep 01

Sass: Do You Need CSS Superpowers?

With today’s increasingly large and complex web applications, Cascading Style Sheets (CSS) is growing rapidly. Unfortunately, the code is becoming unmanageable, easily spanning thousands of lines. An array of browser incompatibilities, vendor prefixes, responsive web design and good practices such as progressive enhancement and graceful degradation, lead to bloated style sheets. This usually results in large, monolithic styles which makes the search function in your favourite text editor your best only friend for finding the properties you need to edit.

But what if there was a better way to manage all of this? Enter Syntactically Awesome Style Sheets (Sass).

CSS with superpowers

What is Sass?

It’s a CSS preprocessor which gives you the power of variables, arithmetic, nesting, conditional statements, partials, loops and mixins. Think of it this way — if CSS is Tony Stark, Sass is Iron Man.

As a super set of CSS3, you can use your current style sheets and sprinkle some Sass throughout, or overhaul your documents as you fully grasp the power it affords.

A couple of use cases for it include:

  • Team collaboration using version control
  • Building themes
  • Quick prototyping with defined mixins/frameworks
Sass is a superset of CSS3

Sass is a superset of CSS3, for the math-inclined.

The Code

Let’s take a look at the SCSS (Sassy CSS) syntax:

Variables

// Sass has line comments, such as this.

/*
* Normal block comments too!
*/

// Variables begin with a $ symbol:
$siteFont: "Arial, sans-serif"; // using a string variable to store the font

// using the $siteFont variable
body {
	font-family: $siteFont;
}

$headerPadding: 1.2em; // storing a number. Sass' number type includes em, px, %
$menuPadding: $headerPadding/2; // You can do arithmetic
$menuBackground: orange;

header {
	padding: $headerPadding;
}

nav {
	padding: $menuPadding 0;
	// using the built in darken function to darken colour by 10%
	background: linear-gradient($menuBackground, darken($menuBackground, 10%));
}

The SCSS syntax is stored in files with the .scss extension. This can then be compiled to plain .css files:

/*
* Normal block comments too!
*/
body {
  font-family: "Arial, sans-serif";
}

header {
  padding: 1.2em;
}

nav {
  padding: 0.6em 0;
  background: linear-gradient(#ffa500, #cc8400);
}

Line comments and variable declarations are not visible in the compiled file above. Notice how $menuBackground: orange is compiled to its hexadecimal value. Sass understands colours (they are actually a datatype) hence the use of darken which is an internal Sass function.

Nesting & Inheritance

$linkColour: #D00;

a {
	color: $linkColour;

	// using nesting and the special parent selector '&'
	&:hover, &:focus { // :hover and :focus states of links
		color: #F00;
	}

	&:active { // :active state of links
		color: lighten($linkColour, 10%); // lighten function
	}

	span {
		color: #000;
	}
}

Nesting can be used to keep your code DRY. In the example below I’ve made use of Sass’ parent selector & which allows you to define pseudo states and more.

a {
  color: #dd0000;
}
a:hover, a:focus {
  color: #F00;
}
a:active {
  color: #ff1111;
}
a span {
  color: #000;
}

Control Structures & Mixins

// @import includes the content & scope of the respective file.
@import "header"; // the _header.scss file in this case

$leftSidebar: true; // sass boolean type

#sidebar {
	/* Side bar style here */
	@if $leftSidebar { // conditional statement using the @if directive
		float: left;
	} @else {
		float: right;
	}
	/* other side bar styles */
}
// This is a partial file
header {
	/* Header styles here */
}

The @import option can be used to combine .scss as well as .css files. This lets you split up your CSS into more manageable sections or modules. Files beginning with an underscore such as _header.scss are called “partials” and are not compiled as separate CSS files. Note the use of @import "header"; which could also have been written as @import "_header";.

This gets compiled to:

header {
  /* Header styles here */
}

#sidebar {
  /* Side bar style here */
  float: left;
  /* other side bar styles */
}

Conditional statements, coupled with variables and @import open up possibilities for making your own configuration files. This can be very helpful when creating themes for example. As mentioned earlier, Sass has internal functions but it also allows you to define your own custom functions. Mixins offer a reusable set of declarations, which you can even pass variables to. They are defined using the @mixin directive. Parameters can also have default values.

// mixin taking parameters $gridColumns and $gridName
// which are optional since they have default values.
@mixin grid($gridColumns: 12, $gridName: '.span') {

	$grid: $gridColumns;

	%grids { // This is a placeholder selector
		display: block;
		float: left;
	}

	@while $grid > 0 {
		#{$gridName}#{$grid} { // .spanX
			@extend %grids; // extends the %grids placeholder selector
			width: percentage( $grid/$gridColumns );
		}

		$grid: $grid - 1; // decrement $grid variable
	}

}

@include grid(4, '.col'); // using the grid mixin

The code above allows the creation of grids based on the Bootstrap 12 column grid system. By passing 4 to the mixin, I defined a 4 column grid system. I’ve also made use of placeholder selectors which begin with the % sign. They are not compiled into the final output unless they’re extended by an exisitng CSS selector using the @extend directive.

The compiled output looks like this:

.col4, .col3, .col2, .col1 {
  display: block;
  float: left;
}
.col4 {
  width: 100%;
}
.col3 {
  width: 75%;
}
.col2 {
  width: 50%;
}
.col1 {
  width: 25%;
}
$PREFIXES: (webkit, moz, ms); // A list

// $colours is a mandatory parameter, $ie is optional
@mixin linear-gradient($colours, $ie: false) {

	@each $prefix in $PREFIXES { // loop through $PREFIXES list
		background: -#{$prefix}-linear-gradient($colours);
	}

	background: linear-gradient($colours);

    @if $ie { // output IE filter gradient?
        $startColour: ie-hex-str(nth($colours, 1));
        $endColour: ie-hex-str(nth($colours, length($colours)));

        filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr=#{$startColour},endColorstr=#{$endColour});
    }

}

.box {
	@include linear-gradient((red, #444, yellow), true); // colours passed as list
}

Any vendor prefixes which you commonly use can be encapsulated in different mixins and used as a template for making your own time-saving frameworks. This can help you to get future projects off the ground quicker as you have a flexible base to work from.

.box {
  background: -webkit-linear-gradient(red, #444444, yellow);
  background: -moz-linear-gradient(red, #444444, yellow);
  background: -ms-linear-gradient(red, #444444, yellow);
  background: linear-gradient(#ff0000, #444444, #ffff00);
  filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr=#FFFF0000,endColorstr=#FFFFFF00);
}

How Do I Get Sass?

Installation

First you need to install Ruby. The installation process for all operating systems is well documented here.

Then in your terminal/command line type the following:

gem install sass

IDEs & Text editors

You can find editor packages/extensions for the following:

How Do I Use Sass?

Once installed (for the non-command-line-phobic) open up a terminal and type the following:

sass --watch path/to/sass:path/to/stylesheets

This will watch your Sass folder for any changes and automatically compile your styles. Here are more options for compilation.

For those allergic to the terminal, here is a list of apps that will do all the heavy lifting for you. I personally prefer using the Compass Build System for Sublime Text 2 & 3.

Hopefully this has been an informative overview of the awesomeness of Sass.

Now…

Go forth, and.. SASS ALL THE THINGS