Sass.
It's a Game-Changer.


Una Kravets / @una


una.github.io/slides-intro-to-sass

IBM Watson Logo

Sass...!?

Sass:

Syntactically Awesome Style Sheets: Sass is the most mature, stable, and powerful professional grade CSS extension language in the world. sass-lang.com

Sass...!?

Sass is a CSS preprocessor.

CSS


.navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret {
  border-top-color: #ffffff;
}
.navbar .nav .active .caret {
  opacity: 1;
  filter: alpha(opacity=100);
}
.navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle {
  background-color: transparent;
}
.navbar .nav .active > .dropdown-toggle:hover {
  color: #ffffff;
}
.navbar .nav.pull-right .dropdown-menu {
  left: auto;
  right: 0;
}
.navbar .nav.pull-right .dropdown-menu:before {
  left: auto;
  right: 12px;
}
.navbar .nav.pull-right .dropdown-menu:after {
  left: auto;
  right: 13px;
}
.breadcrumb {
  padding: 7px 14px;
  margin: 0 0 18px;
  background-color: #fbfbfb;
  background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5));
  background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: -o-linear-gradient(top, #ffffff, #f5f5f5);
  background-image: linear-gradient(top, #ffffff, #f5f5f5);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);
  border: 1px solid #ddd;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -webkit-box-shadow: inset 0 1px 0 #ffffff;
  -moz-box-shadow: inset 0 1px 0 #ffffff;
  box-shadow: inset 0 1px 0 #ffffff;
}
.breadcrumb li {
  display: inline-block;
  text-shadow: 0 1px 0 #ffffff;
}
.breadcrumb .divider {
  padding: 0 5px;
  color: #999999;
}
.breadcrumb .active a {
  color: #333333;
}
.pagination {
  height: 36px;
  margin: 18px 0;
}
.pagination ul {
  display: inline-block;
  *display: inline;
  /* IE7 inline-block hack */

  *zoom: 1;
  margin-left: 0;
  margin-bottom: 0;
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.pagination li {
  display: inline;
}
.pagination a {
  float: left;
  padding: 0 14px;
  line-height: 34px;
  text-decoration: none;
  border: 1px solid #ddd;
  border-left-width: 0;
}
.pagination a:hover, .pagination .active a {
  background-color: #f5f5f5;
}
.pagination .active a {
  color: #999999;
  cursor: default;
}
.pagination .disabled a, .pagination .disabled a:hover {
  color: #999999;
  background-color: transparent;
  cursor: default;
}
.pagination li:first-child a {
  border-left-width: 1px;
  -webkit-border-radius: 3px 0 0 3px;
  -moz-border-radius: 3px 0 0 3px;
  border-radius: 3px 0 0 3px;
}
.pagination li:last-child a {
  -webkit-border-radius: 0 3px 3px 0;
  -moz-border-radius: 0 3px 3px 0;
  border-radius: 0 3px 3px 0;
}
.pagination-centered {
  text-align: center;
}
.pagination-right {
  text-align: right;
}
.pager {
  margin-left: 0;
  margin-bottom: 18px;
  list-style: none;
  text-align: center;
  *zoom: 1;
}
.pager:before, .pager:after {
  display: table;
  content: "";
}
.pager:after {
  clear: both;
}
.pager li {
  display: inline;
}
.pager a {
  display: inline-block;
  padding: 5px 14px;
  background-color: #fff;
  border: 1px solid #ddd;
  -webkit-border-radius: 15px;
  -moz-border-radius: 15px;
  border-radius: 15px;
}
.pager a:hover {
  text-decoration: none;
  background-color: #f5f5f5;
}
.pager .next a {
  float: right;
}
.pager .previous a {
  float: left;
}
            

But Really,
It's a Game-Changer

  • Organization
  • Theming
  • Logic
  • Low Barrier to Entry

Installation and Getting Started

Ruby Sass

  1. ruby
  2. gem install sass
  3. sass –watch input.scss:output.css

Node Sass

  1. node
  2. npm install node-sass
  3. sass –watch input.scss:output.css

Watching folders

Sass Basics


  • Syntax
  • Variables
  • Variable Abstraction
  • Nesting
  • Ampersands
  • Selector Inheritance & @extend
  • Placeholder Selectors
  • Partials & @import

Syntax


.sass

              #sidebar
  width: 30%
  background-color: #faa
  
            
  • Variables: !
  • Assignment: =
  • .scss

                  #sidebar {
      width: 30%;
      background-color: #faa;
    }
                            
    • Variables: $
    • Assignment: :

    Variables


    Placeholders for values used multiple times.

    .scss

                  $open-sans-stack: 'Open Sans', Arial, Helvetica, sans-serif;
    $pink: #c69;
    
    body {
      font-family: $open-sans-stack;
    }
    
    h2 {
      color: $pink;
    }

    .css output

                body {
      font-family: "Open Sans", sans-serif;
    }
    
    h2 {
      color: #c69;
    }

    Variable Abstraction


    Variables should be abstracted into themes.

    .scss

                  // variables.scss
    $open-sans-stack: 'Open Sans', Arial, Helvetica, sans-serif;
    $pink: #c69;
    
    // theme.scss
    $font--copy: $open-sans-stack;
    $header--color: $pink;
    
    
    // typography.scss
    body {
      font-family: $open-sans-stack;
    }
    
    h2 {
      color: $header--color;
    }

    .css output

                body {
      font-family: "Open Sans", sans-serif;
    }
    
    h2 {
      color: #c69;
    }

    Nesting


    Nesting allows you to organize your code in relevant chunks

    .scss

                  .sidebar {
      float: left;
    
      h2 {
        font-size: 1.2em;
      }
    }

    .css output

                  .sidebar {
      float: left;
    }
    .sidebar h2 {
      font-size: 1.2em;
    }

    A word on Nesting

    • Never go more than 3 levels deep
    • Nesting with an & is a-okay

    When Nesting Goes Wrong


    Do not do this.

    .scss

                  body {
      sidebar {
        .news-section {
          .description {
            a {
              color: #f00;
            }
          }
        }
      }
    }

    .css output

                  body sidebar .news-section .description a {
      color: #f00;
    }
    
    judge open comp

    Yay Nesting!


    .scss

                  $blue: #00f;
    
    .blue-link {
      color: $blue;
    
      &:hover,
      &:focus {
        color: mix($blue, white, 50%);
      }
    }

    .css output

                  .blue-link {
      color: #00f;
    }
    .blue-link:hover, .blue-link:focus {
      color: #7f7fff;
    }

    The almighty ampersand

    • Great for BEM, SMACSS & other syntax methodologies
    • No long selectors!
    Ampersand gif

    The Trailing Ampersand


    .scss

                  .unicorn {
      .set-one & {
        display: none;
      }
    }
    
    .button--large {
      .sidebar & {
        font-size: 80%;
      }
    }

    .css output

                  .set-one .unicorn {
      display: none;
    }
    
    .sidebar .button--large {
      font-size: 80%;
    }

    @extend (Selector Inheritance)


    Extending will append the element to recieve the style block.

    .scss

                  .kitten {
      background-image: url("../img/kitten.png");
    }
    
    .kitten-with-hat {
      @extend .kitten;
    
      &:after {
        content: " ";
        background-image: url("../img/hat.png");
      }
    }

    .css output

                  .kitten, .kitten-with-hat {
      background-image: url("../img/kitten.png");
    }
    
    .kitten-with-hat:after {
      content: " ";
      background-image: url("../img/hat.png");
    }

    .kitten


    .kitten-with-hat


    Placeholder Selectors


    Placeholders are "invisible" until extended

    .scss

                  $pink: #c69;
    $blue: #00f;
    
    // I'm not real yet
    %link {
      text-decoration: none;
      font-weight: 300;
    }
    
    .pink-link {
      @extend %link; //extending
      color: $pink;
    }
    
    .blue-link {
      @extend %link; //extending
      color: #00f;
    }

    .css output

                  .pink-link, .blue-link {
      text-decoration: none;
      font-weight: 300;
    }
    
    .pink-link {
      color: #c69;
    }
    
    .blue-link {
      color: #00f;
    }

    Partials & @import


    Sass files are split into "partials" for better organization.

    Manifest File (main.scss)

                  @import "vendors/bootstrap";
    @import "vendors/jquery-ui";
    
    @import "utils/variables";
    @import "utils/functions";
    @import "utils/mixins";
    @import "utils/placeholders";
    
    @import "base/reset";
    @import "base/typography";
    
    @import "layout/navigation";
    @import "layout/grid";
    @import "layout/header";
    @import "layout/footer";
    @import "layout/sidebar";
    @import "layout/forms";
    
    @import "components/buttons";
    @import "components/carousel";
    @import "components/cover";
    @import "components/dropdown";
    
    @import "pages/home";
    @import "pages/contact";
    
    @import "themes/theme";
    @import "themes/admin";
    sass directories

    Using Mixins


  • Mixins & @include
  • Mixins & arguments
  • The arglist...
  • Mixins & @content
  • Mixins & @include


    Mixins are blocks of code you @include

    .scss

                  @mixin center-block {
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    
    .nyan-cat {
      width: 450px;
      @include center-block; //including here
    }

    .css output

                  .nyan-cat {
      width: 450px;
      display: block;
      margin-left: auto;
      margin-right: auto;
    }

    Mixins + Arguments

    Mixins can accept parameters, making them even more flexible

    .scss

                  @mixin box-shadow($shadow) {
      -webkit-box-shadow: $shadow;
         -moz-box-shadow: $shadow;
              box-shadow: $shadow;
    }
    
    .box {
      @include box-shadow(0 0 0 3px #aaa)
    }

    .css output

      .box {
      -webkit-box-shadow: 0 0 0 3px #aaa;
      -moz-box-shadow: 0 0 0 3px #aaa;
      box-shadow: 0 0 0 3px #aaa;
    }
    

    The Arglist


    @mixin shadows($shadows...) {
      box-shadow: $shadows;
    }

    Mixins and @content


    Mixins can take a variety of args, including @content blocks.

    .scss

                  //mixin
    @mixin smaller-than($width) {
      @media (max-width: $width) {
        @content;
      }
    }
    
    @mixin larger-than($width) {
      @media (min-width: $width) {
        @content;
      }
    }
    
    //usage
    .heading {
      font-size: 2em;
      @include smaller-than(300px) {
        font-size: 1.5em;
      }
      @include larger-than(768px) {
        font-size: 3em;
      }
    }

    .css output

                  .heading {
      font-size: 2em;
    }
    @media (max-width: 300px) {
      .heading {
        font-size: 1.5em;
      }
    }
    @media (min-width: 768px) {
      .heading {
        font-size: 3em;
      }
    }

    Control Directives & Functions


    • Lists
    • Maps
    • @each loop
    • @for loop
    • Math
    • Color Functions

    Lists


    Basic List

                  $social-icons: twitter, facebook, instagram, dribbble;

    Space-seperated Values

                  $types: text #f00, photo #c69, video #c0ffee, link #bada55;

    Lists in Action

    Note: Sass Lists start at 1, not 0.


    .scss

                  $types: text #f00, photo #c69, video #c0ffee, link #bada55;
    
    @each $type in $types {
         .post-type-#{nth($type, 1)} .post-icon{
            background: nth($type, 2);
        }
    }

    .css output

                  .post-type-text .post-icon {
      background: #f00;
    }
    
    .post-type-photo .post-icon {
      background: #c69;
    }
    
    .post-type-video .post-icon {
      background: #c0ffee;
    }
    
    .post-type-link .post-icon {
      background: #bada55;
    }

    List Functions


    Maps


    Maps are structured in key: value pairs and accessed with map-get($map-name, key).

    .scss

                  $breakpoints: (
      small: 767px,
      medium: 992px,
      large: 1200px
    );
    
    .sidebar {
      width: 30%;
    
        @media (max-width: map-get($breakpoints, small)) {
          width: 100%;
        }
    }

    .css output

                  .sidebar {
      width: 30%;
    }
    @media (max-width: 767px) {
      .sidebar {
        width: 100%;
      }
    }
    

    Map Functions


    @each loop


    color scheme

    @each loop


    .scss

                    @import 'compass';
    
    $colors: (
      tomato rgb(255,99,71) 'rgb(255,99,71)',
      'cornflowerblue' rgb(100,149,237) 'rgb(100,149,237)',
      gold rgb(255,215,0) 'rgb(255,215,0)',
      hotpink rgb(255,105,180) 'rgb(255,105,180)',
    );
    
    @each $color in $colors {
      $var-name: nth($color, 1);
      $hex: nth($color, 2);
      $css-name: nth($color, 3);
      .color-box.#{$var-name} {
        @include contrasted($hex);
        &:before {
          content: '#{$var-name}';
        }
        &:after {
          content: '#{$css-name}';
        }
      }
    }
    
                  

    .css output

                    .color-box.tomato {
      background-color: tomato;
      color: #000;
    }
    .color-box.tomato:before {
      content: "tomato";
    }
    .color-box.tomato:after {
      content: "rgb(255,99,71)";
    }
    
    .color-box.cornflowerblue {
      background-color: cornflowerblue;
      color: #000;
    }
    .color-box.cornflowerblue:before {
      content: "cornflowerblue";
    }
    .color-box.cornflowerblue:after {
      content: "rgb(100,149,237)";
    }
    
    .color-box.gold {
      background-color: gold;
      color: #000;
    }
    .color-box.gold:before {
      content: "gold";
    }
    .color-box.gold:after {
      content: "rgb(255,215,0)";
    }
    
    .color-box.hotpink {
      background-color: hotpink;
      color: #000;
    }
    .color-box.hotpink:before {
      content: "hotpink";
    }
    .color-box.hotpink:after {
      content: "rgb(255,105,180)";
    }
    
                  

    @for loop


    For loop using through

    .scss

                  $columns: 4;
    
    @for $i from 1 through $columns {
      .cols-#{$i} {
        width: ((100 / $columns) * $i) * 1%;
      }
    }

    .css output

                  .cols-1 {
      width: 25%;
    }
    
    .cols-2 {
      width: 50%;
    }
    
    .cols-3 {
      width: 75%;
    }
    
    .cols-4 {
      width: 100%;
    }

    @for loop


    For loop using to

    .scss

                  $columns: 4;
    
    @for $i from 1 to $columns {
      .cols-#{$i} {
        width: ((100 / $columns) * $i) * 1%;
      }
    }

    .css output

                  .cols-1 {
      width: 25%;
    }
    
    .cols-2 {
      width: 50%;
    }
    
    .cols-3 {
      width: 75%;
    }

    Supported Operators


    Calculation


    • +
    • -
    • *
    • /
    • %

    Comparison


    • ==
    • !=
    • >
    • <

    Number Functions


    Number Functions

    Math with Color


    Input:

    p {
      color: #010203 + #040506;
    }

    01 + 04 = 05, 02 + 05 = 07, and 03 + 06 = 09

    Computed Value:

    p {
      color: #050709;
    }

    Playing with Color


    See the Pen Experiments with Sass Color Functions by KatieK (@KatieK2) on CodePen.

    Note: Mix > Lighten or Darken


    See the Pen Dadgumit, Blowouts by KatieK (@KatieK2) on CodePen.

    Pulling it Together


    • Mixins + Maps
    • A Sassy Shape Mixin
    • Theming with Maps
    • Advanced Trigonometric Sass
    • Sass Weather App

    Mixins and Maps


    .scss

                  //our map of breakpoints from earlier
    $breakpoints: (
      small: 767px,
      medium: 992px,
      large: 1200px
    );
    
    //mixin using map-get
    @mixin smaller-than($point-name) {
    
      $width: map-get($breakpoints, $point-name);
      @media (max-width: $width) {
        @content;
      }
    }
    
    @mixin larger-than($point-name) {
    
      $width: map-get($breakpoints, $point-name);
      @media (min-width: $width) {
        @content;
      }
    }
    
    //usage
    .heading {
      font-size: 2em;
      @include smaller-than(small) {
        font-size: 1.5em;
      }
      @include larger-than(medium) {
        font-size: 3em;
      }
    }

    .css output

                  .heading {
      font-size: 2em;
    }
    @media (max-width: 300px) {
      .heading {
        font-size: 1.5em;
      }
    }
    @media (min-width: 768px) {
      .heading {
        font-size: 3em;
      }
    }

    Sassy Shapes Mixin


    Mixins can take values and run logic loops.

    See the Pen Sassy Shape Machine Mixin by Una Kravets (@unax3) on CodePen.

    Sassy Shapes Mixin


    Putting it to use.

    See the Pen Sassy CSS Puppy by Una Kravets (@unax3) on CodePen.

    Theming using Maps


    variables.scss

                  $__color-palette: (
      'blue': (
        core: #4178be,
        10: #c0e6ff,
        20: #7cc7ff,
        30: #5aaafa,
        40: #5596e6,
        50: #4178be,
        60: #325c80,
        70: #264a60,
        80: #1d3649,
        90: #152935,
        100: #010205
      ),
      'green': (
        core: #4b8400,
        10: #c8f08f,
        20: #b4e051,
        30: #8cd211,
        40: #6eb400,
        50: #4b8400,
        60: #2d660a,
        70: #144d14,
        80: #0a3c02,
        90: #0c2808,
        100: #010200
      ),
      'teal': (
        core: #008571,
        10: #a7fae6,
        20: #6eedd8,
        30: #41d6c3,
        40: #00b4a0,
        50: #008571,
        60: #006d5d,
        70: #005448,
        80: #003c32,
        90: #012b22,
        100: #000202
      ),
      'purple': (
        core: #9855d4,
        10: #eed2ff,
        20: #d7aaff,
        30: #ba8ff7,
        40: #af6ee8,
        50: #9855d4,
        60: #734098,
        70: #562f72,
        80: #412356,
        90: #311a41,
        100: #030103
      ),
      'magenta': (
        core: #db2780,
        10: #ffd2ff,
        20: #ff9eee,
        30: #ff71d4,
        40: #ff3ca0,
        50: #db2780,
        60: #a6266e,
        70: #7c1c58,
        80: #601146,
        90: #3a0b2e,
        100: #040102
      )
    );

    functions.scss

                  // Import the IBM Color Palette
    @import '../variables/colors';
    
    //////////////////////////////
    // Color Palette
    //
    // Gets the specified color from the color palette
    //
    // Usage:
    //
    // background: color('blue', 80); // #1D3649
    // background: color('blue');     // #4178BE
    //////////////////////////////
    @function color($color, $tone: 'core') {
      // Add a little helper so tone can be passed as single digit number
      @if type-of($tone) == 'number' {
        @if $tone % 10 == $tone {
          $tone: $tone * 10;
        }
      }
      @return map-get(map-get($__color-palette, $color), $tone);
    }

    Theming Using Maps


    A better look at functions.scss

                  // Import the IBM Color Palette
    @import '../variables/colors';
    
    //////////////////////////////
    // Color Palette
    //
    // Gets the specified color from the color palette
    //
    // Usage:
    //
    // background: color('blue', 80); // #1D3649
    // background: color('blue');     // #4178BE
    //////////////////////////////
    @function color($color, $tone: 'core') {
      // Add a little helper so tone can be passed as single digit number
      @if type-of($tone) == 'number' {
        @if $tone % 10 == $tone {
          $tone: $tone * 10;
        }
      }
      @return map-get(map-get($__color-palette, $color), $tone);
    }

    Advanced Trigonometric Functions


    See the Pen Pure CSS 3D animated icosidodecahedron (pentagonal gyrobirotunda) by Ana Tudor (@thebabydino) on CodePen.

    Ana Tudor, FTW


    See the Pen Cube truncation sequence (pure CSS 3D animation) by Ana Tudor (@thebabydino) on CodePen.

    Jackie Balzer


    More Resources

    Thank You