Capistrano

What is SASS?

You may know about some of the problems that CSS has as a language. There is a lot of repetition. There is a lot of repetition. You may have worked on projects with 5000 lines of CSS. Not only is that a lot of code to write, but it's also a lot of code to maintain. But what about its smarts?


What is SASS and why should I care?

If you've done this:

p {
color:#f00;
}
p a {
color:#f00;
}

Or this:


.content {
width: 240px /* Content is 300px wide - div padding - border */
}

…then you know about some of the problems that CSS has as a language. There is a lot of repetition. There is a lot of repetition. You may have worked on projects with 5000 lines of CSS. Not only is that a lot of code to write, but it's also a lot of code to maintain. But what about its smarts? CSS has some neat tricks, but not a whole lot of logic. You can't say "Make this headline a little darker than the background color" or "If this container is longer than 500px, set the overflow to hidden." SASS allows us to do all of this and more. It also wins the Awesome Acronym award for having awesome right in there: Syntactically Awesome Style Sheets.

Preprocessed CSS

I can hear groans from front-end devs now. I know because I did it too at one point. If you went through the early days of HTML preprocessing than you might remember some of the headaches of working with those new systems. "Where did that element come from?" or "Why didn't anything change?". Those were interesting but confusing days that eventually led to great debuggers and better compilers. SASS comes in long after the hard problems have been solved. Yes, you will be looking at compiled code. However there are built in ways to work with this depending on your style of coding. Some of us will be excited about this jump to compiled logical stylesheets and some of us won't be; you know who you are. You're the same set that was building table based layouts after 2000. That's ok, we'll drag you along eventually, too.

To get something out of the way right now, there are two syntax styles available to SASS. The first actual SASS syntax uses the Haml style of indentation. I'm much more of a fan of the SCSS syntax and it's CSS-like structure.

CSS Organization

Nesting

You'll never do this again:


#content p {
padding:10px;
color:black;
}
#content p a {
color:black;
}
#content img {
border:1px solid black;
}
#content p img {
border:1px solid red;
}
#content p.small {
padding:5px;
}
#content p.small a {
color:red;
}

In SASS:

$color = black;
#content {
p {
padding:10px;
color:$color;
a {
color:$color;
}
&.small {
padding:5px;
a {
color:red;
}
}
img {
border:1px solid red;
}
}
img {
border:1px solid black;
}
}

Ok, I know what some of you are thinking… "That's 19 lines instead of 22!" And you're right, but the advantages of this can be seen pretty quickly. Instead of trying to figure out the level of your selector, you simply see it. When you start using Mixins and variables, the scss will continually get lighter.

Partial Style Sheets

This may seem like a small issue, but being able to separate the individual components from the whole has many benefits, the least of which is better organization. Picture a structure like this:

print.css
default.css
style.css

That can be a little hard to find stuff in, but it's necessary to keep HTTP requests down. Now take a look at this:

scss
  ∟default.scss
  ∟common
    ∟_variables.scss
    ∟_colors.scss
    ∟_fonts.scss
  ∟forms
    ∟_buttons.scss
    ∟_fields.scss
    ∟_validation.scss
  ∟content
    ∟_main.scss
    ∟_sidebar.scss
  ∟images
    ∟_gallery.scss
    ∟_inline.scss
    ∟_lightbox.scss
  ∟header
    ∟_logo.scss
    ∟_navigation.scss
    ∟_search.scss
  ∟footer
    ∟_legal
    ∟_footer-nav

You could compile all of these into the one default.scss stylesheet by using this code:

@import "common/_variables.scss";
@import "common/_colors.scss";
@import "common/_fonts.scss";
@import "forms/_buttons.scss";
@import "forms/_fields.scss";
@import "forms/_validation.scss";
@import "content_main.scss";
@import "content_sidebar.scss";
@import "images/_gallery.scss";
@import "images/_inline.scss";
@import "images/_lightbox.scss";
@import "header/_logo.scss";
@import "header/_navigation.scss";
@import "header/_search.scss";
@import "footer/_legal";
@import "footer/_footer-nav";

And SASS will output one default.css file.

Now your page is still only making the one HTTP request for the CSS but your source is broken up into many easy to identify chunks. This may sound like more work and smaller projects may not need to go to this level of organization, but for larger projects it will save hours.

Logical CSS

Variables

This is probably one of the biggest features of SASS. Variables allow us a standardized way to handle values that may be changed or are repeatedly used throughout the code. Ever been asked to change a color in CSS? It's no longer a nightmare! Simply go into your _color.scss file and make the replacement. No more search and replace! I'll get into some of the fancier ways this can be used a little later.

Operators

I can't guess how many times I've wanted to use basic arithmetic in my CSS. "This div should be 10px taller than the .navigation class" or "The height of this div is this other element's height + it's padding + it's border." We now have logical operators. This is now valid:


div.next {
height: 10px + $navigation_height;
}

And

div.other {
height: $other_element_height + $other_element_padding + $other_element_border;
}

Of course these would require that the variables were set up somewhere else in your file, but they demonstrate the potential.

Mixins

Functions in CSS! Yay! Turns this:


p, div, #navigation {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-ms-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
}
p {
-webkit-box-shadow: 10px 10px 10px black;
-moz-box-shadow: 10px 10px 10px black;
-ms-box-shadow: 10px 10px 10px black;
-o-box-shadow: 10px 10px 10px black;
box-shadow: 10px 10px 10px black;
}
div {
-webkit-box-shadow: 10px 10px 10px red;
-moz-box-shadow: 10px 10px 10px red;
-ms-box-shadow: 10px 10px 10px red;
-o-box-shadow: 10px 10px 10px red;
box-shadow: 10px 10px 10px red;
}
#navigation {
-webkit-box-shadow: 10px 10px 10px blue;
-moz-box-shadow: 10px 10px 10px blue;
-ms-box-shadow: 10px 10px 10px blue;
-o-box-shadow: 10px 10px 10px blue;
box-shadow: 10px 10px 10px blue;
}

into this:

@mixin shadow($color: black) {
-webkit-box-shadow: 10px 10px 10px $color;
-moz-box-shadow: 10px 10px 10px $color;
-ms-box-shadow: 10px 10px 10px $color;
-o-box-shadow: 10px 10px 10px $color;
box-shadow: 10px 10px 10px $color;
}
@mixin rounded {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-ms-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
}
p, div, nav {
@import box;
}
p {
@import shadow;
}
div {
@import shadow(red);
}
#navigation {
@import shadow(blue);
}

The main difference being that you can now apply the same rounded corners or shadow to any element in your css with one line. If your shadow changes site-wide, you still only make one change. You can even pass in variables and use default values.

Control Statements

You can also use controls like 'if' , 'for', and 'each' statements directly in your CSS. While this is still an experimental feature that is only recommended for use in mixins, you can quickly see how it will change how you write your CSS:

if


$type: monster;
p {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}

compiles to:

p {
color: green;
}

for


@for $i from 1 through 3 {
.item-#{$i} { width: 2em * $i; }
}

compiles to

.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
.item-3 {
width: 6em;
}

each


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

compiles 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'); }

Working with SASS

Compass/LiveReload/Whatever

Yes, SCSS does need to be compiled, but it doesn't have to be a chore. There are a number of programs available that will watch the SCSS folder for changes and recompile when it sees a file has been changed. I personally use Compass, for both its watching and also its fantastic list of library functions, which I'll touch more on in a moment.

Where's my code?

When you compile your css, you're no longer going to be able to just inspect the code and find the line number, as you're working in a different file than the css. But there are ways around that, too. There is a way to compile using comments with the source line numbers. These can be automatically fed to FireSASS, a plugin to tell you the real line numbers in FireFox, or you can use my method: click on the class, which opens the css file. Right above the selector is the comment that tells me which file and line numbers to look for. Just remember to turn this off before you go to production, just to reduce the file size.

Extras

Compass is worth looking at if only for the watch feature, but it comes with a litany of extra mixin libraries to get you started very quickly.

Color manipulation

Wouldn't it be cool if you could do this?

color: darken($blue, 9%);

You can! How cool is that? You could build an entire design based on colors made from calculations on one color. You can lighten, desaturate, get the complimentary color, increase or decrease opacity, etc. The possibilities are mind-boggling.

Spriting

If you've ever worked with sprites and had to generate them, then you will be floored by Compass' ability to work with sprites. Simply create a folder of logically named images: icons/rss.png, icons/twitter.png, icons/fb.png, icons/logo.png, etc. and then insert these lines of code into your css:

@import "icon/*.png";
@include all-icon-sprites;

You'll then get this output:

.icon-rss,
.icon-twitter,
.icon-fb,
.icon-logo { background: url('/images/icon-s34fe0604ab.png') no-repeat; }

.icon-rss { background-position: 0 0; }
.icon-twitter { background-position: 0 -32px; }
.icon-fb { background-position: 0 -64px; }
.icon-logo { background-position: 0 -96px; }

With all of the coordinates ALREADY THERE. Anybody who's worked with sprites knows why I used all caps there. For those people, prepare to be blown away. What about rollovers, you say? Simply add these to the folder: icons/rss_hover.png, icons/twitter_hover.png, icons/fb_hover.png, icons/logo_hover.png and it will output this:

.icon-rss,
.icon-twitter,
.icon-fb,
.icon-logo { background: url('/images/icon-s34fe0604ab.png') no-repeat; }

.icon-rss { background-position: 0 0; }
.icon-twitter { background-position: 0 -32px; }
.icon-fb { background-position: 0 -64px; }
.icon-logo { background-position: 0 -96px; }
.icon-rss:hover { background-position: 30 0; }
.icon-twitter:hover { background-position: 30 -32px; }
.icon-fb:hover { background-position: 30 -64px; }
.icon-logo :hover { background-position: 30 -96px; }

What? No! OMG, For realz? Yes, for real. Go check out SASS and Compass now.

If you are interested in integrating Compass and Capistrano, we wrote about that too.

Similar posts

Get notified on new marketing insights

Be the first to know about new B2B SaaS Marketing insights to build or refine your marketing function with the tools and knowledge of today’s industry.