Learning SASS and Compass – Tools – Workflow: Dev/test



Learning SASS and Compass – Tools – Workflow: Dev/test

0 0


sass-lunch-learn

Learning SASS and Compass

On Github iowacodeninja / sass-lunch-learn

Learning SASS and Compass

Or, CSS With Superpowers

by Christa Dickson

What You're In For

What is SASS?

  • A CSS pre-compiler
  • Allows you to use helpful programming concepts in your CSS:
    • Variables
    • Functions
    • Includes

Full Sass Documentation

What is Compass?

  • A framework for SASS
  • Comes with pre-packaged functions & mixins
    • resets
    • color helpers
    • sprites
    • grids
    • CSS3 helpers

Full Compass Documentation

Just so we're clear...

  • SASS is the language
  • Compass is the framework
  • By their powers combined we get CSS

Why should we use it?

  • It's faster to write than normal CSS
  • Makes nesting simpler, easier to manage
  • Makes implementation of CSS3 features easier/faster
  • Makes maintenance easier down the road
  • Enables us to be smart and reusable with our code
  • Plus, it's neat!

Any Drawbacks?

  • Ease of nesting can lead to overly verbose code
  • Style overrides can get tricky to find
  • Sprite generation/management is buggy, especially with our setup
  • New workflows/setup/learning curve

Tools

So what do we need to get SASSy?

  • Text editor
  • Local Compass instance (Ruby)

We use...

  • jRuby
  • gem install of Compass
  • A homegrown IntelliJ plugin

Other options:

  • Scout, Compass.app
    • easier to setup, but less configurable
  • Command line install of Ruby and Compass
    • seriously easy

Workflow: Local dev environment

Set up a Compass project Set up a folder watch Write SASS code (file.scss) The watch compiles SASS to CSS on save (file.css)

Workflow: Dev/test

  • Commit the .scss files to dev/test
  • At build time, all .scss files are compiled to .css files

Important Note!

You won't ever edit or commit the .css files.

EVAR.

SASS/Compass Features

Nesting

#navbar {
  width: 80%;
  height: 23px;

  ul { list-style-type: none; }
  li {
    float: left;
    a { font-weight: bold; }
  }
}

Outputs To:

#navbar {
  width: 80%;
  height: 23px; }
  #navbar ul {
    list-style-type: none; }
  #navbar li {
    float: left; }
    #navbar li a {
      font-weight: bold; }
                        

Nesting 201

Pseudo classes and the Almighty Ampersand

a {
  color: #ce4dd6;
  &:hover { color: #ffb3ff; }
  &:visited { color: #c458cb; }
}						

Outputs To:

a {
  color: #ce4dd6; }
  a:hover {
    color: #ffb3ff; }
  a:visited {
    color: #c458cb; }

Nesting: Things to Note

Nesting tags within each other translates to a SPACE (descendant selector).

#siteContainer{
  .block{}
}
/* Outputs to... */ 
#siteContainer .block{}

Nesting: &:pseudo or &.class

Using the ampersand in FRONT removes the space.

#siteContainer{
  &.block{}
  &:hover{}
}
/* Outputs to... */ 
#siteContainer.block{}
#siteContainer:hover{}

Nesting: .class &

Using the ampersand BEHIND specifies a parent selector.

#siteContainer{
  color: red;
  .blue &{
    color: blue;
  }
}
/* Outputs to... */
#siteContainer{ color: red; }
.blue #siteContainer{ color: blue; }

Variables

Variables are used to store/reuse commonly used pieces of information

$green: #8fc357;

#siteNavContainer{
  background-color: $green;
}

Variable Math

You can do addition, subtraction, multiplication and division on variables.

$margin: 16px;

.border {
  padding: $margin / 2;
  margin: $margin + 5px;
}

Variable Output/Interpolation

This standard output format will work in most cases:

color: $green; 

But what if you want to use the variable as part of the property name?

/* doesn't work */
border-$direction: 1px solid $green;

/* does work */
border-{$direction}: 1px solid $green;

@import - CSS Includes

Allows you to include smaller stylesheets inside larger ones.

@import "partials/filename"

Fun with Partials

@import "partials/filename"
  • The files you include are called 'partials'
    • Partials usually begin with an underscore, e.g., _base.scss
    • The underscore tells SASS not to compile them to their own stylesheets
  • You can import libraries (like Compass) or your own partials
  • Partials are awesome because they allow to you to split up large files into small pieces and then recombine later

Import Example

/* include the Compass framework */
@import "compass";

/* include a file inside your folder, 'partials/_colors.scss' */
@import "partials/colors";

Mixins

Mixins are reusable, configurable chunks of CSS.

@include my-mixin;

Two types of mixins:

  • Pre-built mixins (from Compass)
  • Roll-your-own mixins

Example: Using a Compass Mixin

/* turns a bulleted list into a horizontal list */

ul.horizontal{
  @include horizontal-list;
}

Some Useful Compass Mixins/Functions

HTML Reset

Old way:

<link href="/web/css-min/common/css/html5Reset.css" rel="stylesheet"> 

New way:

@import "blueprint/reset"; 

Color Manipulation

$green: #128c7f;
$light-green: lighten($green, 20%);
$dark-green: darken($green, 20%);

Other Color Methods

Browser Prefix Management

Old way:

.rounded-corner{
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  -khtml-border-radius: 4px;
  border-radius: 4px; 
}

New way:

.rounded-corner{ 
  @include border-radius(4px); 
}

Other Browser Prefix Helpers

Grids

Grids require math. Compass does the math for you!

// grid setup
$blueprint-grid-columns: 9;
$blueprint-grid-margin: 20px; 
$blueprint-grid-width: 90px;

#siteContainer{
  @include container;
}
#mainColumn{
  @include column(6);
}
#rightColumn{
  @include column(3);
  @include last;
}

Sprites

Compass gives you tools to generate sprites automagically.

@import "my-icons/*.png";

Sprite Basic Steps

Put individual PNGs in a folder under images Define spacing/orientation Your sprite is generated at compile/build time
@import "my-icons/*.png";
.actions {
  .new    { @include my-icons-sprite(new);    }
  .edit   { @include my-icons-sprite(edit);   }
}

Sprite Benefits

  • You don't have to keep track of where the image is in the sprite... you can call it by name
  • You can get dimensions/position from mixins
    $width: my-icons-sprite-width(new);
  • Code is more human-readable

Sprite Drawbacks

  • Sprite order is inconsistent (alpha vs. by file size)
    • Unusable for retina versions
  • Assumes sprites will be on your local filesystem (vs. Interwoven)
  • No compression
  • If you update and forget to commit an image file, builds will fail

Sprite Verdict

  • Good for original generation
  • Not so good for upkeep
  • One option... use Compass to generate original sprite, then take generated CSS moving forward

Full Compass sprite documentation

Mixins 201:

Rolling Your Own Mixin

@mixin green-me(){
  background-color: #9f9;
  border: 2px solid #096;
}

p{
  @include green-me;
}

Passing Arguments to Mixins

You can define arguments to be passed into your mixin to change the output.

@mixin green-me($border-style: solid){
  background-color: #9f9;
  border: 2px $border-style #096;
}

p{
  @include green-me($border-style: dashed);
}

Using Logic in Mixins

You can use basic control structures (if/else, for loops) in mixins.

@mixin color-me($color: blue, $border-style: solid){
  @if $color == blue{
    background-color: #b2deed;
    border: 2px $border-style #008bb4;
  }@else if $color == green{
    background-color: #9f9;
    border: 2px $border-style #096;
  }
}

p{
  @include color-me($color: green, $border-style: dashed);
}

When to Use a Mixin vs. a Partial

  • In general, mixins should be used for shorter chunks of code
  • Partials should be used when there's larger chunks
  • The more mixins you add, the longer it takes to compile
  • The more partials you have, the more confusing your file structure

Balance it out somewhere in the middle.

Functions

Similar to mixins, but they generally use math or logic to return a value (rather than a set of styles).

/* Compass span function: returns a width in columns */
@function span($n) {
  @return $blueprint-grid-width * $n 
  	 + $blueprint-grid-margin * ($n - 1); 
}

#mainColumn{
  width: span(6);
}  

Understanding Mixins vs. Functions

  • Mixins usually output CSS rules
  • Functions usually output a property value or other piece of a CSS rule
/* this is the column mixin (does floating, margin and width) */
#mainColumn{
  @include column(6);
}
/* this is the span function (just returns width) */
#mainColumn{
  width: span(6);
}

Specific problems we solved with SASS for Parents.com

Creating responsive & non-responsive versions of stylesheets

We used imports of partials with media queries.

// ---- core-responsive.scss ---
/* mobile layout */
@media screen and (max-width: 653px){
  @import "partials/narrow/core";
}
/* tablet portrait */
@media screen and (min-width: 654px){
  @import "partials/normal/core";
}
/*  Widescreen layout */
@media screen and (min-width: 990px){
  @import "partials/wide/core";
}  

// ---- core.scss ---
@import "partials/narrow/core";
@import "partials/normal/core";
@import "partials/wide/core";

Identical image.css and secureimage.css

Same trick, with additional variables

// ---- image.scss ----
$secure: false;
@import "partials/image";

// ---- secureimage.scss ----
$secure: true;
@import "partials/image";

// ---- partials/image.scss ----
$image_path: "http://images.meredith.com/parents/";
$secure_image_path: "https://secure.parents.com/parents/";
@if $secure{
  $image_path: $secure_image_path;    
}

#header{
  background: url("#{$image_path}image.png";
}

Example Code: Output

                        
/* ---- image.css ---- */
#header{ 
  background: url("http://images.meredith.com/image.png"; 
}

/* ---- secureimage.css ---- */
#header{ 
  background: url("https://secure.parents.com/image.png"; 
}

Built a reusable mixin library

a.more{ 
  @include block-more-link;
}

ul{
  @include pink-bullets;
}

.blogModule{
  @include content-box;
}

.up{
  @include triangle($direction: up, $size: 10px);
}

Try It Yourself!

More Links

Questions?

christa.dickson@meredith.com