PREPROCESS ALL THE THINGS!

An Introduction to CSS Preprocessors

Chris Harrison · @cdharrison

Atlanta Web Design Group · 6 Feb 2014

Hi, I'm Chris!

HASHTAG ALL THE THINGS!

#AWDGCSS

Before CSS

The look of elements was controlled via inline attributes:


2 LEGIT 2 QUIT
HEY HEY

In short: it was painful to author/maintain.

And then CSS happened.

And we were able to use inline styles like this...


ZOMGOSH.

(Which wasn't much better than inline attributes.)

Or this...

(Via Inline Stylesheets)




ZOMG! No inline styles?! DOUBLE RAINBOW!

Or this...

Where we finally separated style from content
via external stylesheets!




ZOMG! No styles in my HTML?! DOUBLE RAINBOW!

It was magical, trust me.

But CSS is far from perfect.

  • No variables
  • Multiple HTTP Requests
  • Non-Reusable
  • PITA Browser Prefixes

Fortunately,
there's a better way!

But first, a Disclaimer:

CSS Preprocessors won't fix terrible CSS.

What's a CSS Preprocessor?

CSS Preprocessors compile the CSS we write in a processed language into the pure CSS syntax we're all used to.

Why use a CSS Preprocessor?

  • Frameworks, Variables, Mixins
  • Modular, Reusable, Extendable CSS
  • DRY Syntax (Don't Repeat Yourself)
  • And...

If you can write CSS, you can write LESS, Sass, or Stylus.

Popularity of CSS Preprocessors

Sass 5%
Scss 13%
LESS 23%
Stylus 3%
I don't like any of them 7%
I don't have a preference 2%
I've never tried any of them 46%
Other 1%

[June 2012] CSS Tricks: Popularity of CSS Preprocessors — hrrsn.me/TmDg

LESS

Written in Javascript, LESS extends CSS with dynamic behaviors like variables, mixins, operations, and functions.

.less - add less.js to your <head> you can link to .less files, just like you would .css.

lesscss.org

Basic LESS Usage



Sass

Written in Ruby, Sass also extends CSS by adding nested rules, variables, mixins, functions, and much more. Two syntaxes:

.sass - concise, omits colons and brackets
.scss - functions as an extension of CSS syntax

sass-lang.com

Stylus

Expressive, robust, feature-rich CSS language built for nodejs. Supports both an indented syntax and regular CSS style.

.styl - optionally omit colons, semi-colons, brackets and more

learnboost.github.io/stylus/

How can I use a
CSS Preprocessor?

  • Compile Locally
  • Client-side Compiling
  • Compile and Cache On-Demand (Server-Side)
  • Compile on Deploy

Just starting out?

Use a GUI

Some of them are really, really good.

Codekit

Process Less, Sass, Stylus, Jade, Haml, Slim, CoffeeScript, Javascript and Compass files automatically each time you save.

incident57.com/codekit/

Compass.app

Compass.app is a menubar only app for Sass and Compass. It helps designers compile stylesheets easily without resorting to command line interface.

compass.kkbox.com

Koala

Koala is a GUI application for Less, Sass, Compass and CoffeeScript compilation, to help web developers to use them more efficiently.

koala-app.com

Prepros

Prepros compiles LESS, Sass, SCSS, Stylus, Jade, Slim, Coffeescript, LiveScript, Haml and Markdown.

alphapixels.com/prepros/

Syntax

The most important part of writing code in a CSS preprocessor is understanding the syntax. Luckily for us, the syntax is (or can be) identical to regular CSS for all three preprocessors.

Sass (SCSS) or LESS

Sass (SCSS) and LESS both use standard CSS syntax. This makes it extremely easy to convert an existing CSS file to either preprocessor.


/* style.scss or style.less */
h1 {
  color: #00afee;
}

/* style.sass */
h1
  color: #00afee
					

Stylus

Stylus accepts standard CSS syntax + other variations where brackets, colons, and semi-colons are all optional.


/* style.styl */
div.masthead {
  background: #00afee;
}

/* omit brackets */
div.masthead
  background: #00afee;

/* omit colons and semi-colons */
div.masthead
  background #00afee
					

Variables

Variables are a way to store reusable strings that you can reference throughout your stylesheet(s).

Use them to store things like colors, font stacks, etc.

SCSS


$main-color: #006;
color: $main-color;

LESS


@main-color: #006;
color: @main-color;

Stylus


main-color = #006
color main-color

Mixins

Reusable sets of properties or rules that you can include or mix into other rules.

SCSS Mixins


@mixin pad($x, $y) {
  padding: $y $x;
}
.msg {
  @include pad(5px, 10px);
}
.msg { padding: 5px 10px; }

LESS Mixins


.pad(@x, @y) {
  padding: @y @x;
}
.msg {
  .pad(5px, 10px);
}
.msg { padding: 5px 10px; }

Stylus Mixins


pad(x, y)
  padding y x
.msg
  pad(5px, 10px)

@import

Just like CSS, you can import additional stylesheets into a main document. With preprocessors, there aren't multiple HTTP request. Compiled CSS = 1 combined stylesheet.


@import "file.less"; // LESS
@import "file"; // Assumes .sass or.scss
@import "mixins/border-radius" // Assumes .styl
@import "style.css" // Stylus - literal

And now here's the part where
I stop talking about LESS & Stylus.

Sass Partials

Chunks of CSS that you are included in other Sass files.

These don't compile directly.

Reuse as you see fit.


// filename: _menu.scss
@import "_menu";
// OR:
@import "menu";

Underscore (_) is optional with @import. Sass checks for it automatically.


// File Structure
+ scss/core.scss		// Primary Sass file
	@import "mixins"; 	// _mixins.scss
	@import "colors"; 	// _colors.scss
	@import "typography";	// _typography.scss
	@import "masthead";	// _masthead.scss
	@import "nav";		// _nav.scss

// It'd compile them all into one CSS file:
+ css/core.css

Underscore (_) is optional with @import. Sass checks for it automatically.

Nesting

HTML has a fairly clear nested, visual hierarchy. CSS doesn't.

Sass lets you nest your CSS selectors in a way that follows the same logical structure.

Instead of writing repetitive selectors...


header#masthead h1.logo{
  font-family: Papyrus;
  font-size: 15px;
}
header#masthead h1.logo a{
  color: #ffe100;
}

You can nest child selectors within the parent.


header#masthead{
  h1.logo{
    font{
      family: Papyrus;
      size: 15px;
    }
    a{
      color: #ffe100;
    }
  }
}
  • Keep it DRY (Don't Repeat Yourself).
  • Don't nest too deeply.

&

The Referencing Parent Selector allows you to refer back to a parent when constructing a nested selector.

This:


h1{
  font-size: 24px;
  &.tagline{
    font-size: 48px;  
  }
}

Compiles to this:


h1{ font-size: 24px; }
h1.tagline{ font-size: 48px; }

Color Functions

lighten(), darken(), rgba(), hsla()


lighten($color,$amount)
darken($color,$amount)
rgba($color,$opacity)
hsla($color,$opacity)

$awdgRed: #de3831;

a.logo{
  background: $awdgRed;
  &:hover{
    background: darken($awdgRed,25);
  }
  &:active{
    background: rgba($awdgRed,.75);
  }
}

This compiles to: → colors.css

Nested Media Queries

Allow you to keep media queries within their original context.

Nested Media Query

Here, we can change the <h1> font-size based on viewport max-width.


h1{
  font-size: 4em;
  @media screen and (max-width:480px){
    font-size: 2em;
  }
  @media screen and (max-width:320px){
    color: #c00;
    font-size: 1.5em;
  }
}

But what if you want to change your breakpoints?

Conditional MQ Mixin


@mixin bp($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 600px)  { @content; }
  }
}

How you'd use it


h1{
  font-size: 4em;
  @include bp(mama-bear){
    font-size: 2em;
  }
  @include bp(baby-bear){
    color: #c00;
    font-size: 1.5em;
  }
}

CSS Tricks - Conditional Media Query Mixins - hrrsn.me/Tlub

Operators

Sass has a handful of standard math operators like +, -, *, /, and %.

Sass Operators

Here, we can calculate the width of the sidebar based on the width and columns.


// SCSS
$width: 960px;
$col: 6;
#sidebar{
  width: ($width/$col);
}

// BECOMES
#sidebar{ width:160px; }

%foo & @extend

Placeholder selectors look just like class or id's but they're used with @extend. Used on their own, they aren't compiled into your CSS.


%clearfix{
  zoom:1;
  &:before,&:after {
    content: "\0020";
    display: block;
    height: 0;
    overflow: hidden;
  }
  &:after { clear: both; }
}
header{ @extend %clearfix; }

// Or you can extend other selectors
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

placeholder.css

Demo Time

Grab the Demo Project Files: hrrsn.me/Tm0k

Frameworks & Libraries

Bootstrap, Foundation, Compass, Bourbon & More...

hrrsn.me/RzyE

Even Moar Reading

A collection of links on CSS Preprocessors, online tools, and more.

hrrsn.me/Rzwm

Slides

speakerdeck.com/cd

You got this.

Stay in Touch

Thank you.