Fasten RWD Development
with Sass

Sven Wolfermann | maddesigns

Who is the guy?

Sven Wolfermann - Certified TYPO3 Integrator

Sass
old

Sass Logo new
new

What is Sass?

Installing Sass

In order to install and run Sass, you need to have Ruby installed on your system.

Mac OSX

Easy! Ruby is built in :)

Linux

if not installed, use the package manager

$ sudo apt-get install ruby

on Windows?

use http://rubyinstaller.org/ to install ruby

Installing Sass

$ sudo gem install sass

install beta version:

$ sudo gem install sass --pre

already installed Sass?

check with

$ sass --version

Sass or SCSS?

Sass has two syntaxes. The new main syntax is known as “SCSS” (for “Sassy CSS”). SCSS files use the extension .scss.

The second, older syntax is known as the indented syntax (or just “Sass”). Instead of brackets and semicolons, it uses the indentation of lines to specify blocks. Files in the indented syntax use the extension .sass.

SCSS

section {
  margin: 1em 0;
  header {
    background-color: lightpink;
  }
}

Sass

section
  margin: 1em 0
  header
    background-color: lightpink
        

compiling to CSS - watch changes

open terminal

$ sass input.scss output.css

watch folder

$ sass --watch sass:css
    

watch file

$ sass --watch sass/style.scss:css/style.css
    

GUIs

many GUIs for compiling

and build in in many text editors or IDEs

Variables

working with variables

h1 {
  border-bottom: 2px solid #000000; // black
  color: #FF8700; // orange
  margin: 0 0 0.5em;
}

change to global variables

$brand-color1: #000000;
$brand-color2: #FF8700;

h1 {
  border-bottom: 2px solid $brand-color1;
  color: $brand-color2;
  margin: 0 0 0.5em;
}

Variables

variables can be colors, sizes, percentage, ...

$page_max_width: 1200px;
$padding: 20px;
.container {
  min-height: 100%;
  max-width: $page_max_width;
  width: auto;
  margin: 0 auto;
  padding: 0 $padding;
}

Calculating with Sass

SCSS

.container {
  max-width: $page_max_width - $padding * 2;
  padding: 0 $padding;
  ...
}

CSS

.container {
  max-width: 1160px; /* 1200px - 20px * 2 */
  padding: 0 20px;
  ...
}

Old box model calculation

Nesting

Nesting

writing long selectors is time consuming

short selectors are better in general

CSS

nav {float: right;}
nav li {float: left;}
nav li a {color: #666;}
nav li a:hover {color: #333;}
nav li.current {font-weight: bold;}
  

Nesting

SCSS

nav {
  float: right;
  li {
    float: left;
    a {
      color: #666;
      &:hover {
        color: #333;
      }
    }
    &.current {
      font-weight: bold;
    }
  }
}
  

Nesting

HOW DEEP CAN I GO?

Sass nesting != HTML nesting

be careful with nesting!

you can run into performance issues with long selectors

Combining Selectors

Combining Selectors

div {
  color: black
  .foo {
    color: black } // descendant
  + .foo {
    color: black } // adjacent
                   // sibling
  > .foo {
    color: black } // child
  ~ .foo {
    color: black } // general
                   // sibling
  & .foo {
    color: black } // Sass' parent
                   // selector
  &.bar {
    color: black }
  &:hover {
    color: black }
}
div {
  color: black; }
div .foo {
  color: black; }
div + .foo {
  color: black; }

div > .foo {
  color: black; }
div ~ .foo {
  color: black; }

div .foo {
  color: black; }

div.bar {
  color: black; }
div:hover {
  color: black; }

Parent Selector - the ampersand

the & (ampersand) has a placeholder function for the parental selector

a {
  &:hover,
  &:focus {
    color: black
  }
}
  
a:hover, a:focus {
  color: black;
}
  

Parent Selector - the ampersand

Usecase for Modernizr classes

div {
  box-shadow: 0 0 5px rgba(#000, 0.8);
  // Sass feature for Hex to RGB colors
  .no-boxshadow & {
    border: 1px solid #555;
  }
}
  
div {
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.8); }

.no-boxshadow div {
  border: 1px solid #555; }

Parent Selector - the ampersand

div {
  .parent & .child {
    color: black
  }
}
  
.parent div .child {
  color: black;
}
  

Importing Files

Importing

the way in CSS

/* style.css */
@import "base.css";
@import url("styles.css");
@import url("druck.css") print;

Importing CSS files into one file can cause performance issues

Limit your external references in your HTML

Importing in Sass is better

split your stylesheet in many chunks and use the import function of Sass

Importing

@import "modules/base";
@import "partials/header", "partials/footer";
  

create subfolders and devide into partials

use underscore in your filenames to concatinate the partials within the compiling process

Importing

Imagine this structure

/style.sass
/modules/
 ┗ _normalize.sass
 ┗ _base.sass
 ┗ _mixins.sass
/partials/
 ┗ _footer.sass
 ┗ _header.sass
/ie.sass
/print.sass

none underscore files will be compiled into seperate CSS files

Importing

# style.sass
@import modules/normalize
@import modules/base
@import modules/mixins
@import partials/header
@import partials/footer
@import ie
@import print

this compiles to 3 files:

/css
┗ style.css
┗ ie.css
┗ print.css

@extend

@extend

@extend clones the attributes from rules and adds them to another rule.

.button {
  background-color: $color-main;
  font-weight: bold;
  color: white;
  padding: 5px;
}

Then we can @extend the class to another

.button-checkout {
  @extend .button;
  background-color: darken($color-main, 20%);
}

@extend

.button-checkout {
  @extend .button;
  background-color: darken($color-main, 20%);
  .msg & {
    @extend .button;
    background-color: darken($color-main, 30%);
  }
}
.button, .button-checkout, .msg .button-checkout {
  background-color: blue;
  font-weight: bold;
  color: white;
  padding: 5px; }

.button-checkout {
  background-color: #000099; }
.msg .button-checkout {
  background-color: #000066; }

Placeholder Selectors: %foo

// This ruleset won't be rendered on its own.
%button {
  color: blue;
  font-weight: bold;
  font-size: 2em; }

placeholder selectors can be extended, just like classes and IDs. The extended selectors will be generated, but the base placeholder selector will not

.btn-notice { @extend %button; }
.btn-notice {
  color: blue;
  font-weight: bold;
  font-size: 2em; }

%placeholder

placeholder selectors will not be rendered to CSS.

%button {
  background-color: $color-main;
  font-weight: bold;
  color: white;
  padding: 5px;
}

.button-checkout {
  @extend %button;
  background-color: darken($color-main, 20%);
}
.button-checkout {
  background-color: #000099;
  font-weight: bold;
  color: white;
  padding: 5px; }

@mixin

Man, tell me the cool things!

Mixins

Are code snippets (reusable elements)

Parameterizable (use reasonable defaults)

@mixin border-radius($value) {
  -webkit-border-radius: $value;
  -moz-border-radius: $value;
  border-radius: $value;
}
.box {
  color: $color-main;
  font-family: $helvetica-font-stack;
  @include border-radius(5px);
}
  

Mixins

compiled to

.box {
  color: blue;
  font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  border-radius: 5px;
}

but thats a bad example – no need for the vendor prefixes of border-radius anymore

only use border-radius: 5px; in your stylesheets

Functions

Functions

Operators

Relational operators (<, >, <=, >=) evaluate numbers

1 < 20 // true
10 <= 20 // true
4 > 1 // true
4 >= 1 // true

Comparison operators (==, !=) evaluate all data types

1 + 1 == 2 // true
small != big // true
#000 == black // true
  

Functions

Control Directives

@if
@for
@each
@while

$theme: ocean;
div {
  @if $theme == dusty {
    background: #c6bba9;
    color: $color;
  } @else if $theme == ocean {
    background: blue;
    color: white;
  }
}

Media-Queries with Sass

Parent Selector - the ampersand

@media queries in place

aside {
  width: 100%;
  @media screen and (min-width: 680px) {
    width: 25%;
  }
}
aside {
  width: 100%;
}
@media screen and (min-width: 680px) {
  aside {
    width: 25%;
  }
}

Variables in queries

use main breakpoints as variables

$break-small: 320px;
$break-large: 1200px;

.profile-pic {
  float: left;
  width: 100px;
  @media screen and (min-width: $break-small) {
    width: 250px;
    float: none;
  }
  @media screen and (min-width: $break-large) {
    float: right;
  }
}

Mixin for different media queries using @content

$break-small: 320px;
$break-large: 1200px;

@mixin respond-to($media) {
  @if $media == smartpones {
    @media only screen and (max-width: $break-small) {
      @content;
    }
  } @else if $media == tablet {
    @media only screen and (min-width: $break-small + 1)
                       and (max-width: $break-large - 1) {
      @content;
    }
  } @else if $media == desktop {
    @media only screen and (min-width: $break-large) {
      @content;
    }
  }
}

Mixin for different media queries using @content

Usage

// profile picture module
.profile-pic {
  display: block;
  @include respond-to(smartpones) { float: left; width: 125px; }
  @include respond-to(tablet) { width: 125px; }
  @include respond-to(desktop) { width: 33%; }
}

Mixin for different media queries using @content

CSS output sample

.profile-pic {
  display: block;
}
@media only screen and (max-width: 320px) {
  .profile-pic {
    float: left;
    width: 125px;
  }
}
@media only screen and (min-width: 321px) and (max-width: 1199px) {
  .profile-pic {
    width: 125px;
  }
}
@media only screen and (min-width: 1200px) {
  .profile-pic {
    width: 33%;
  }
}

mobile first and IE8

Sass-IE

Writing mobile-first styles without leaving IE < 9 behind

Media Query Mixin:

// all.scss

$fix-mqs: false !default;

@mixin respond-min($width) {
    // If we're outputting for a fixed media query set...
    @if $fix-mqs {
        // ...and if we should apply these rules...
        @if $fix-mqs >= $width {
            // ...output the content the user gave us.
            @content;
        }
    }
    @else {
        // Otherwise, output it using a regular media query
        @media screen and (min-width: $width) {
            @content;
        }
    }
}
// and a respond-max mixin, that does what you might expect

Sass-IE

OldIE Mixin:

// all.scss
$old-ie: false !default;

@mixin old-ie {
    // Only use this content if we're dealing with old IE
    @if $old-ie {
        @content;
    }
}

	

Separate IE stylesheet

// all-old-oldie.scss
$old-ie: true;
$fix-mqs: 65em;

@import 'all';

Including the Sass-IE CSS

To give the CSS to the browsers, use good old conditional comments:

<!--[if lte IE 8]>
    <link rel="stylesheet" href="css/all-old-ie.css">
<![endif]-->

<!--[if gt IE 8]><!-->
    <link rel="stylesheet" href="css/all.css">
<!--<![endif]-->

Debugging

Debugging in Sass 3.3

Sourcemaps to work with original files in developer tools

scss --sourcemap sass/styles.scss public/styles.css

Include in Sass:

/*# sourceMappingURL=styles.css.map */

Sassmaps output

{
  "version": "3",
  "mappings": "4DAUA,qFAWQ,CACJ,OAAO,CAAE,KAAK,CAOlB,…",
  "sources": ["../sass/_vars.css”,”../sass/styles.scss"],
  "file": "styles.css"
}

Compass

Compass

Compass is to Sass like jQuery to Javascript

Compass is a Framework, that extends Sass
It brings a lot of CSS3 mixins and useful CSS stuff

current version is a bit outdated, wait for 1.0

Compass Plugins

Github List of Compass Plugins

loading Compass plugins

add to the config.rb

# config.rb
...
require 'compassplugin'
@import 'compassplugin';

Compass plugins

Responsive Grid Plugin – Singularity – Grids without limits

$ sudo gem install singularitygs
$ compass create myproject -r singularitygs --using singularitygs
    

Add Singularity plugin to existing projects

# config.rb
require "singularitygs"
@import 'singularitygs';

Symmetric Grids - Twitter Bootstrap

$grids: 12;
$gutters: 1/3;
Twitter Bootstrap Grid

Symmetric Grids - Zurb Foundation

$grids: 12;
$gutters: 0.9375em;
$gutter-style: split;
Zurb Foundation Grid

Asymetric Grids with Singularity

$grids: 1 4 1;
$gutters: 1/6;
$gutter-style: split;
Asymetric Grid

Singularity Usage

Isolation grids as default

@include grid-span($span, $location);


// Span 1 column, starting at the 2nd column
.span1-pos2 {
  @include grid-span(1, 2);
}

// Span 3 columns, starting at the 3rd column
.span3-pos3 {
  @include grid-span(3, 3);
}

// Span 5 columns, starting at the 7th column
.span5-pos7 {
  @include grid-span(5, 7);
}

Singularity Extras

proportional Grids (Golden Grid)

Compass plugins

simple media queries Sass plugin – Breakpoint

$ gem install breakpoint

Add plugin to projects

# config.rb
require "breakpoint"
// main.scss
@import "breakpoint";

Breakpoint plugin usage

// basic media queries, min-width and min/max width
$basic: 543px;
$pair: 456px 794px;

.foo {
  content: 'No Media Queries';

  @include breakpoint($basic) {
    content: 'Basic Media Query';
  }

  @include breakpoint($pair) {
    content: 'Paired Media Query';
  }
}

Breakpoint plugin CSS output

/* Nested Breakpoint calls become separate media queries */
.foo {
  content: 'No Media Queries';
}

@media (min-width: 543px) {
  .foo {
    content: 'Basic Media Query';
  }
}

@media (min-width: 456px) and (max-width: 794px) {
  .foo {
    content: 'Paired Media Query';
  }
}
	

Breakpoint Media Types

$breakpoint-to-ems: true;
$media: 'screen' 700px;

#foo {
  @include breakpoint($media) {
    content: 'Media';
  }
}
@media screen and (min-width: 43.75em) {
  #foo {
    content: 'Media';
  }
}

High Resolution Media Querys

@import "breakpoint";
.sample {
  color: red;

  @include breakpoint(min-resolution 2dppx) {
    color: green;
  }
}
.sample {
  color: red;
}
@media (min-resolution: 2dppx),
       (-webkit-min-device-pixel-ratio: 2),
       (min--moz-device-pixel-ratio: 2),
       (min-resolution: 192dpi) {
  .sample {
    color: green;
  }
}

IE8 Fallback

// _layout.scss
// global breakpoints
$small: 24em;
$middle: 34em;
$large: 65em, 'no-query' true;

.component {
  color: red;
  @include breakpoint($middle) {color: blue}
  @include breakpoint($large) {color: green;}
}
// styles.scss
$breakpoint-no-queries: false;
$breakpoint-no-query-fallbacks: false;
@import 'layout';
// fallback-ie8.scss
$breakpoint-no-queries: true;
@import 'layout';

IE8 Fallback

styles.css

.component {
  color: red;
}
@media (min-width: 34em) {
  .component {
    color: blue;
  }
}
@media (min-width: 65em) {
  .component {
    color: green;
  }
}

fallback-ie8.css

.component {
  color: red;
  color: green;
}

Fixed Ratio Box

easy embedding images with fixed ratios or iframes

.some-class {
  @include fixed-ratiobox(16/9, 100%, 'img');
}

http://sassmeister.com/gist/9335167

Fixed Ratio Box

.some-class {
  position: relative;
  height: 0;
}

.some-class img {
  display: block;
  position: absolute;
  width: 100% !important;
  height: 100% !important;
  top: 0;
  margin: 0;
  padding: 0;
}

.some-class {
  padding-top: 56.25%;
  width: 100%;
}

Team Sass on Github

lot of Sass goodies

Questions?

Thanks for your attention!

Sven Wolfermann | maddesigns

http://maddesigns.de/rwd-sass-compass/