CSS Preprocessors

Sass, Less and Stylus

Patrick Arlt - @patrickarlt

Some Background

I'm an Designer and Developers at Geoloqi Esri.

Design, UX, HTML, CSS, JS, lots of it everyday...

Ok Ok, which is best?

Really Short Answer

SASS or Stylus

Slightly Longer Answer

SASS if you are using Ruby. Stylus if you using Node. LESS if you afraid of the command line.

80/20

80% of SASS, LESS and Stylus is the same.

The 20% that is different is in advanced usage.

Installing

SASS
$ gem install sass
$ sass --watch style.scss:style.css
LESS
<link rel="stylesheet/less" type="text/css" href="styles.less">
<script src="less.js" type="text/javascript"></script>
$ npm install less
$ lessc styles.less
Stylus
$ npm install stylus
$ stylus css --watch

The 80%

Variables

Color Transformation

Mixins

Nesting

Loops & Conditionals

Importing

Variables

SASS
$button-background: #27adec;
.btn {
  background: $button-background;
}
LESS
@button-background: #27adec;
.btn {
  background: @button-background;
}
Stylus
button-background = #27adec
.btn
  background button-background

Color Transformations

SASS
lighten(@color, 10%);
LESS
mix($dark-blue, $light-blue, 25%);
Stylus
body
  color: #444 + #111;

LESS Mixins

.bordered {
  border: 1px solid #000;
  border-top-color: #444;
  border-bottom-color: #444;
}

#main {
  .bordered;
}

Without Params

.border-radius (@r) {
  -webkit-border-radius: @r;
  -moz-border-radius: @r;
  border-radius: @r;
}

#main {
  .border-radius(4px);
}

With Params

SASS Mixins

@mixin border-radius ($radius: 5px) {
  -webkit-border-radius: $radius;
  -moz-border-radius: $radius;
  border-radius: $radius;
}

#main {
  @include border-radius(4px);
}

Stylus Mixins

border-radius(n)
  -webkit-border-radius n
  -moz-border-radius n
  border-radius n

#main
  border-radius(5px)

Nesting

You can nest selectors in all three frameworks.

#main{
  margin: 0 auto;

  .title {
    font-size: 4em;
  }

  a {
    text-decoration: none;
    &:hover {
      text-decoration: underline;
    }
  }

}

Imports

All 3 support importing from other files or libraries...
@import "compass/css3";
@import "susy";
@import "animation/animate";
@import "myfile.scss";

#main {
  @include border-radius(5px); // from compass/css3
  @include span-columns(10); // from susy
  @include animation(fadeIn); // from animation/animate
  background: $background-color; // from myfile.scss
}

#sidebar {
  @include span-columns(2 omega); // from susy
}

More Features

  • Conditionals like "if, "when"
  • MATH!

SASS and Stylus

  • Loops like "for", "while", and "each"
  • Much more depth then LESS
  • Custom functions without the Ruby/JS API

The 20%

SASS

@extend

@media

@content

@extend

.button {
  background: $blue;
  color: #fff
}

.my-special-button {
  @extend .button;
  font-size: 2em;
}
.button, .my-special-button {
  background: $blue;
  color: #fff
}

.my-special-button {
  font-size: 2em;
}

@extend Selectors

// This won't be compiled
#context a%extreme {
  color: red;
  font-weight: bold;
  font-size: 2em;
}

.notice {
  @extend %extreme;
}
#content a.notice {
  color: $red;
  font-weight: bold;
  font-size: 2em;
}

@media

Declare media queries inside selectors

#content {
  width: 65%;
  margin: 0 auto;
  @media only screen and (max-width : 767px) {
    width: 90%;
  }
}
#content {
  width: 65%;
  margin: 0 auto;
}
@media only screen and (max-device-width : 768px) {
  #content {
    width: 90%;
  }
}

@content

My favorite SASS feature. Lets you pass whole style blocks into mixins. Similar to Rubys "yeild". Use it for...

  • Media Query Helpers
  • Retina Images
  • IE Specific Styles
  • CSS3 Polyfills

@content Example

<!--[if IE 7 ]><html class="ie ie7" lang="en"><![endif]-->
<!--[if IE 8 ]><html class="ie ie8" lang="en"><![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"><!--<![endif]-->
@mixin for-ie(){
  html.ie &{
    @content;
  }
}
#browser-warning {
  display:none;
  @include for-ie(){
    display:block
  }
}

Compass

Compass makes SASS even more awesome

LESS

Mixins

Namespaces

Scoped Variables

Client Side Processing

Mixins

In LESS every class is a mixin

.clearfix() {
  zoom: 1;
  &:before { content: ''; display: block; }
  &:after { content: ''; display: table; clear: both; }
}

#content {
  .clearfix();
}

Namespaceing Mixins

Organize your mixins into namespaces

#my-framework {
  .button () {
    display: block;
    border: 1px solid @dark-blue;
    background-color: @blue;
    color: @light-blue;
  }
}

.a-button {
  #my-framework > .button;
}

Scoped Variables

Variables have scope which makes them it easy to override

@text-color: #444;
@background-color: #fafafa;

body {
  color: @text-color;
  background: @background-color;
}

.inverse {
  @text-color: #fafafa;
  @background-color: #444;
  color: @text-color;
  background: @background-color;
}

h1 { color: @text-color + #111; }

Client-Side Compiling

  • Great for static HTML sites
  • Sites where you don't have a real server (S3)
  • You can evaluate Javascript in your .less files

Evalute Javascipt

You can evalute a javascript expression as a variable

@height: `document.body.clientHeight`;
@width: `document.body.clientWidth`;

Stylus

Syntax

Language Features

@keyframes

Javascript API

Stylus Syntax

  • Whitespace Based
  • Can omit { : ; }
border-radius()
  -webkit-border-radius arguments
  -moz-border-radius arguments
  border-radius arguments

body
  font 12px Helvetica, Arial, sans-serif

a.button
  border-radius(5px)

The biggest problem I have with Stylus is with its syntax

Stylus Language

Stylus feels very much like a simple programming language

  • Ruby-like ranges [1..5], [0...5]
  • for/in loops
  • real operator precidence
  • complex conditionals if/else if/else, unless/else, postfix conditionals

@keyframe Support

CSS3 keyframes are awesome, Stylus makes then easy

@keyframes pulse
  0%, 100%
    -webkit-transform translateX(0);

  20%, 60%
    -webkit-transform translateX(-10px);

  40%, 80%
    -webkit-transform translateX(10px);

This is awesome!

Javascript API

You could do a whole talk on the Stylus API, here are some ideas...

  • Declare really custom functions
  • Use Node modules like canvas
  • Do Compass-like sprite generation
  • Create your own CSS framework

Nib

  • CSS3 helpers - gradiants, border-radius, ect...
  • Mixins for common css patterns
  • Extends CSS with new properties and values
#feedback
  fixed: bottom right
#logo
  image: '/img/logo.png'
h1
  overflow: ellipsis

Smackdown!

Who Wins?

LESS Looses

LESS just doesn't have the features or power of SASS or Stylus

  • Nothing like Compass or Nib
  • No plugin system
  • Can't define your own functions with just LESS
  • Doesn't output any debugging info

SASS vs. Stylus

Both have similar features, a powerful plugin ecosystem, and lots of CSS3 helpers.

  • SASS syntax is close to CSS
  • Stylus is closer to a programming language
  • If you use Ruby you will probally use SASS
  • If you use Node you will probally use Stylus

Questions

Patrick Arlt - @patrickarlt