Modern Frontend Development with Sass & Compass

Introduction

tweet: @maddesigns #sass

Sven Wolfermann | maddesigns

Who is the guy?

Sven Wolfermann - Certified TYPO3 Integrator
CSS is awesome

CSS needs an upgrade

CSS3 ist not enough…

Recommended knowledge for this tutorial

No PHP Knowledge nessessary*

*can contain tracks of Ruby

Short intro to HTML5 Boilerplate

Short intro to Modernizr

Sass

What is Sass?

Sass means syntactically awesome style sheets

is a preprocessor

Similar preprocessors: LESS, Stylus (needs JS, i.e. a node.js server

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 ruby1.9.1-full

Installing Sass (Ruby first)

on Windows?

use http://rubyinstaller.org/

Installing Sass

$ sudo gem install sass

install beta version (3.2.):

$ sudo gem install sass --pre

already installed Sass?

check with

$ sass --version

Create your first Sass (SCSS) file

create a sass folder

create styles.scss

open in your favourite editor*

Wait? What is the SCSS-thingy?

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
        
SCSS is easier for beginners, Sass is more strict and clean
Sven Wolfermann, 2011

First steps

wrap the HTML elements in the H5BP template

  <div class="container">
    <header>
      <h1>header</h1>
    </header>
    <div role="main" class="content">

    </div>
    <footer>
      <p>footer</p>
    </footer>
  </div>
        

First steps

crating first styles in style.scss

html,
body {
  height: 100%;
}

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

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

Uuh... looks like CSS, isn't it?

compile to CSS - watch changes

open terminal

watch folder

$ sass --watch sass:css
    

watch file

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

First steps

compiled to /css/style.css

html, body {
  height: 100%; }

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

h1 {
  border-bottom: 2px solid #69A550;
  color: #FF8700;
  margin: 0 0 0.5em; }

no real difference, but first step done

Variables

working with variables

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

change to global variables

$color-main: #69A550;
$color-alt: #FF8700;

h1 {
  border-bottom: 2px solid $color-main;
  color: $color-alt;
  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;
}

Variables

Variables can be include dashes or underscores

they're compatible to each other and are the same!

$variable-name: value;
.foo {
  property: $variable_name;
}

$variable-name and $variable_name both refer to the same variable

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;
  ...
}

Variables in queries

doesn't work in Sass 3.1 – fixed in Sass 3.2

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

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

Variables in queries, using @content

$break-small: 320px;
$break-large: 1024px;
@mixin respond-to($media) {
  @if $media == handhelds {
    @media only screen and (max-width: $break-small) {
      @content;
    }
  }
  @else if $media == medium-screens {
    @media only screen and (min-width: $break-small + 1)
                       and (max-width: $break-large - 1) {
      @content;
    }
  }
  @else if $media == wide-screens {
    @media only screen and (min-width: $break-large) {
      @content;
    }
  }
}

Variables in queries, using @content

.profile-pic {
  float: left;
  width: 250px;
  @include respond-to(handhelds) { width: 100% ;}
  @include respond-to(medium-screens) { width: 125px; }
  @include respond-to(wide-screens) { float: none; }
}
  

Variables in queries, using @content

.profile-pic {
  float: left;
  width: 250px;
}
@media only screen and (max-width: 320px) {
  .profile-pic {
    width: 100%;
  }
}
@media only screen and (min-width: 321px) and (max-width: 1023px) {
  .profile-pic {
    width: 125px;
  }
}
@media only screen and (min-width: 1024px) {
  .profile-pic {
    float: none;
  }
}

Calculating with Sass

$width: 10px;
$double_width: $width * 2;  /* 20px */
$half_width: $width / 2;    /*  5px */
$width_plus_2: $width + 2;  /* 12px */
$width_minus_2: $width - 2; /*  8px */

spaces are important

Division - a special case

font: 18px / 1.45em; // 18px/1.45em
font: (20px / 5); // 4px
font: 20px / 5 + 1; // 5px
font: $base / 5; // 4px
$size: 20px / 5; // 4px

in the end you come to such solutions

h1, .h1 {
  font: px2em($base-fontsize * 2) / #{$base-lineheight} $font-main;
}
Sample will be explained later

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

identation with SCSS makes no difference in CSS output

SCSS

nav {float: right;
li {float: left;
a {color: #666;
&:hover {
color: #333;}
}
&.current {
font-weight: bold;}
}}
  
but sure it looks better if intended

Nesting

CSS rules aren't the only things that can be nested in Sass. Properties can, too.

.foo {
  border: {
    style: solid;
    width: 1px 2px 3px 4px;
    color: red green blue black;
  }
}
  

Nesting

HOW DEEP CAN I GO?

Sass nesting != HTML nesting

be careful with nesting!

you can run into performance issues with long selectors

Bad Nesting

div.container {
  div.content {
    div.articles {
      & > div.post {
        div.title {
          h1 {
            a {
            }
          }
        }
        div.content {
          ul {
            li { ... }
          }
        }
      }
    }
  }
}

Bad Nesting

div.content div.container { ... }
div.content div.container div.articles { ... }
div.content div.container div.articles > div.post { ... }
div.content div.container div.articles > div.post div.title { ... }
div.content div.container div.articles > div.post div.title h1 { ... }
div.content div.container div.articles > div.post div.title h1 a { ... }
div.content div.container div.articles > div.post div.content { ... }
div.content div.container div.articles > div.post div.content ul { ... }
div.content div.container div.articles > div.post div.content ul li { ... }

Combining Selectors

Combining Selectors

SCSS

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

Combining Selectors

CSS

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

div {
  .foo {
    color: black
  }
  & .foo {
    color: black
  }
}

are compiled to the same

div .foo {
    color: black
}

Parent Selector - the ampersand

div {
  &.foo {
    color: black
  }
}
  
div.foo {
  color: black;
}
  

Parent Selector - the ampersand

div {
  &:hover {
    color: black
  }
}
  
div:hover {
  color: black;
}
  

Parent Selector - the ampersand

div {
  background-color: rgba(#000, 0.8);
  // Sass feature for Hex to RGB colors
  .no-rgba & {
    background-color: black;
  }
}
  
div {
  background-color: rgba(0,0,0, 0.8); }

.no-rgba div {
  background-color: black; }

Parent Selector - the ampersand

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

Parent Selector - the ampersand

SCSS

aside {
  width: 25%;
  .index & {
    width: 30%;
  }
}
aside {
  width: 25%
}
.index aside {
  width: 30%
}

Parent Selector - the ampersand

@media rules in place

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

BTW did you recognize the Comments?

/* Hey look at this multiline comment
* that we want to show up in our CSS output. */
.container {
  color: black; }

// These comments are single lines and
// we do not want them to appear in our CSS
footer {
  color: #336699; }

This compiles to:

/* Hey look at this multiline comment
* that we want to show up in our CSS output. */
.container {
  color: black; }
footer {
  color: #336699; }

Nesting

@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; }

@extend

be careful with extending

try to extend only single rules

.my-layout {
  margin: 1px;
  h1 {
    font-weight: bold;
    font-size: 2em;
  }
  h2 {
    @extend h1;
    font-size: 1.5em;
  }
}
.home-page { @extend .my-layout; }
.about-page { @extend .my-layout; }
.login-page { @extend .my-layout; }
.register-page { @extend .my-layout; }
.my-layout h1, .home-page h1, .about-page h1, .login-page
h1, .register-page h1, .my-layout h2, .home-page .my-layout
h2, .my-layout .home-page h2, .about-page .my-layout h2, .mylayout
.about-page h2, .login-page .my-layout h2, .mylayout
.login-page h2, .register-page .my-layout h2, .mylayout
.register-page h2, .my-layout .home-page h2, .homepage
.my-layout h2, .home-page h2, .about-page .home-page
h2, .home-page .about-page h2, .login-page .home-page h2, .homepage
.login-page h2, .register-page .home-page h2, .homepage
.register-page h2, .my-layout .about-page h2, .aboutpage
.my-layout h2, .home-page .about-page h2, .about-page .homepage
h2, .about-page h2, .login-page .about-page h2, .aboutpage
.login-page h2, .register-page .about-page h2, .aboutpage
.register-page h2, .my-layout .login-page h2, .loginpage
.my-layout h2, .home-page .login-page h2, .login-page .homepage
h2, .about-page .login-page h2, .login-page .about-page
h2, .login-page h2, .register-page .login-page h2, .loginpage
.register-page h2, .my-layout .register-page h2, .registerpage
.my-layout h2, .home-page .register-page h2, .registerpage
.home-page h2, .about-page .register-page h2, .registerpage
.about-page h2, .login-page .register-page h2, .registerpage
.login-page h2, .register-page h2 {
  font-weight: bold;
  font-size: 2em;
}
Redundant selectors were also sometimes created by nested selectors using @extend. That redundancy has been eliminated as well.

Mixins

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

Mixins

Defaults and named arguments

@mixin link-colors($text:blue, $hover:red) {
  color: $text;
  &:hover { color: $hover; }
}

a {
  @include link-colors($hover: green);
}
a { color: blue; }
a:hover { color: green; }

Mixins

SCSS

@mixin my-btn($color) {
  color: $color;
}
@include my-btn(red);

Sass

=my-btn($color)
  color: $color

+my-btn(red)

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 partials/ie
@import partials/print

this compiles to 3 files:

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

Importing

maybe one day you will come to such a structure...

// Libraries                           // Layout
@import compass                        @import public/layout
@import public/config                  @import public/lightbox
@import public/reset                   @import public/images
@import shared/avantgarde
@import public/mixins                  // Forms
@import public/sprites                 @import public/form_styles
@import shared/payment_types           @import public/form_layout
                                       @import public/messaging
// Typography
@import public/type_styles
@import public/type_layout
@import public/links
@import public/pagination

Importing

Nested Imports

Unlike plain CSS, Sass allows @imports to appear inside CSS rules.

So if one file, named _foo.scss, contained this:

.foo {foo: bar}

And then another imported it, like so:

.bar {@import foo}
// same as
.bar {
  .foo {foo: bar}
}

Importing

And because Sass is compiled to CSS, you can import CSS files in your Sass files too

@import foo.css
@import lightbox.css

Convert your old CSS files

# Convert CSS to SCSS
$ sass-convert style.css style.scss

# Convert CSS to Sass
$ sass-convert style.css style.sass

# Convert SCSS to Sass
$ sass-convert style.scss style.sass

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

Color Functions

RGB Functions

rgb($red, $green, $blue)
rgba($red, $green, $blue, $alpha)
rgba($color, $alpha)
red($color)
green($color)
blue($color)
mix($color-1, $color-2, [$weight])

Functions

Color Functions

HSL Functions

hsl($hue, $saturation, $lightness)
hsla($hue, $saturation, $lightness, $alpha)
hue($color)
saturation($color)
lightness($color)
adjust-hue($color, $degrees)
lighten($color, $amount)
darken($color, $amount)
saturate($color, $amount)
desaturate($color, $amount)
grayscale($color)
complement($color)
invert($color)

Functions

Color Functions

Opacity Functions

alpha($color) / opacity($color)
rgba($color, $alpha)
opacify($color, $amount) / fade-in($color, $amount)
transparentize($color, $amount) / fade-out($color, $amount)

Other color functions

adjust-color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])
scale-color($color, [$red], [$green], [$blue], [$saturation], [$lightness], [$alpha])
change-color($color, [$red], [$green], [$blue], [$hue], [$saturation], [$lightness], [$alpha])

Functions

Number Functions

percentage(13/25) // 52%
round(2.4) // 2
ceil(2.2) // 3
floor(2.6) // 2
abs(-24) // 24
  

If Functions

$main-bg: #000;
.main {
  color: if($main-bg == black, #fff, #000);
}

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;
  }
}

Functions

@for loop

@for $level from 0 to 5 {
  .tag-#{$level + 1} {
    font-size: .7em + ($level * .5em);
  }
}
.tag-1 { font-size: 0.7em; }
.tag-2 { font-size: 1.2em; }
.tag-3 { font-size: 1.7em; }
.tag-4 { font-size: 2.2em; }
.tag-5 { font-size: 2.7em; }

Functions

@each $section in home, about, archive, projects {
  nav {
    .#{$section} & {
      background-image: url(/images/nav/#{$section}.png);
    }
  }
}
.home nav {
  background-image: url(/images/nav/home.png); }
.about nav {
  background-image: url(/images/nav/about.png); }
.archive nav {
  background-image: url(/images/nav/archive.png); }
.projects nav {
  background-image: url(/images/nav/projects.png); }

Functions

User Functions

@function grid-width($cells) {
  @return ($cell-width + $cell-padding) * $cells;
}

Function to calculate the em font size from pixels

@function px2em($font_size, $base_font_size: 16) {
  @return $font_size / $base_font_size + em
}

new in Sass 3.2

Placeholder Selectors: %foo

// This ruleset won't be rendered on its own.
#context a%extreme {
  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

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

new in Sass 3.2

#{} interpolation is now allowed in all plain CSS directives (such as @font-face, @keyframes, and of course @media).

Sass 3.2 adds the ie-hex-str function which returns a hex string for a color suitable for use with IE filters.

Sass 3.2 adds the min and max functions, which return the minimum and maximum of several values.

There is now much more comprehensive support for using @extend alongside CSS3 selector combinators (+, ~, and >). These combinators will now be merged as much as possible.

Fun with Sass functions

Compass

Compass

Compass is a Framework, that extends SASS

It brings a lot of CSS3 mixins and useful CSS stuff

Installation

Installation

$ sudo gem install compass

or simple use the new Mac Installer

GUIs

Installation

Create a new project

$ compass create <myproject>

Compass creates following:

config.rb
sass
┗ ie.scss
┗ print.scss
┗ screen.scss
stylesheets
┗ ie.css
┗ print.css
┗ screen.css

Configuration

Configuration

The compass configuration file is a ruby file, which means that we can do some clever things if we want to. But don’t let it frighten you; it’s really quite easy to set up your project.

Standard configuration: config.rb

http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"
  

configuration

my favourite config.rb

# config.rb
http_path = "/"
css_dir = "css"
sass_dir = "sass"
images_dir = "img"
javascripts_dir = "js"
fonts_dir = "fonts"

#environment = :production
relative_assets = true
line_comments = false
output_style = :compact
#output_style = (environment == :production) ? :compressed : :expanded

Production Stylesheets

$ compass compile -e production --force

Create a separate configuration file for production

$ cp config.rb prod_config.rb

# ..edit prod_config.rb to suit your needs..

$ compass compile -c prod_config.rb --force

Importing Compass in Sass files

@import "compass"

importing only few parts

@import "compass/css3"
@import "compass/utilities"
@import "compass/typography/links"

don't care, will not blow your stylesheet unless you use a mixin from Compass

Using Compass Snippets

Sample: Compass Horizontal List

ul.nav {
  @include horizontal-list-container;
  > li {
    @include horizontal-list-item;
  }
}

Sample: Compass Horizontal List

ul.nav {
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  *zoom: 1; }
ul.nav > li {
  list-style-image: none;
  list-style-type: none;
  margin-left: 0;
  white-space: nowrap;
  display: inline;
  float: left;
  padding-left: 4px;
  padding-right: 4px; }
ul.nav > li:first-child, ul.nav > li.first { padding-left: 0; }
ul.nav > li:last-child { padding-right: 0; }
ul.nav > li.last { padding-right: 0; }

CSS3 Mixins

CSS3 Mixins

most CSS3 features are implemented with browser vendor prefixes

think about linear-gradient – hard to know the right syntax

.gradient {
  background-color: yellow; /* Fallback Color */
  background: -webkit-gradient(linear,left top,left bottom,from(yellow),to(blue));
  background: -webkit-linear-gradient(top, yellow 0%, blue 100%);
  background:    -moz-linear-gradient(top, yellow 0%, blue 100%);
  background:     -ms-linear-gradient(top, yellow 0%, blue 100%);
  background:      -o-linear-gradient(top, yellow 0%, blue 100%);

  /* current W3C standard, not implemented
     implemented with prefix in FF10, Opera 11.60 */
  background:      linear-gradient(to bottom, yellow 0%, blue 100%);
}

CSS3 Mixins

easy with Compass

.gradient {
  @include background(linear-gradient(top, yellow, blue));
}

full browser support

.gradient {
  $experimental-support-for-svg: true;
  @include background(linear-gradient(top, yellow, blue));

  // for older IEs
  .oldie & {
    background-color: yellow;
    @include filter-gradient(yellow, blue, vertical);
  }
}

CSS3 Mixins

compiled to

.gradient {
  background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0i.....');
  background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffff00), color-stop(100%, #0000ff));
  background: -webkit-linear-gradient(top, #ffff00, #0000ff);
  background: -moz-linear-gradient(top, #ffff00, #0000ff);
  background: -o-linear-gradient(top, #ffff00, #0000ff);
  background: -ms-linear-gradient(top, #ffff00, #0000ff);
  background: linear-gradient(top, #ffff00, #0000ff);
}
.oldie .gradient {
  background-color: yellow;
  *zoom: 1;
  filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0, startColorstr='#FFFFFF00', endColorstr='#FF0000FF');
}

Global variables

// _base.scss
$experimental-support-for-svg: true;
$support-for-original-webkit-gradients: false;
$legacy-support-for-ie6: false;
$legacy-support-for-ie7: false;

more configuration: Compass Configuration

Helper Functions

Helper Functions

header {
  background: image-url("header-bg.png");
  h1 {
    height: image-height("logo.png");
    width: image-width("logo.png");
    background: transparent inline-image("logo.png") no-repeat;
  }
}
header {
  background: url('../img/header-bg.png');
}
header h1 {
  height: 185px;
  width: 140px;
  background: transparent url('data:image/png;base64,/9j/4AAQSkZJRgABAgAAZABkAAD....') no-repeat;
}

Helper Functions

really useful helper functions

// reads the width of the image
image-width($image)
// reads the height of the image
image-height($image)
// converts the image to an inline image
inline-image($image, $mime-type)
aside {
  #{headings(2,4)} {
    text-transform: uppercase;
  }
}
aside h2, aside h3, aside h4 {
  text-transform: uppercase; }

Sprites

the best feature of Compass

Sprites

Automatic spriting

public/images/icon/new.png
public/images/icon/edit.png
public/images/icon/save.png
public/images/icon/delete.png
  
@import "icon/*.png";
@include all-icon-sprites;
  

Generates sprite images of given folder

Compass watches image folders for changes

Sprites

CSS

.icon-sprite,
.icon-delete,
.icon-edit,
.icon-new,
.icon-save   { background: url('/images/icon-s34fe0604ab.png') no-repeat; }

.icon-delete { background-position: 0 0; }
.icon-edit   { background-position: 0 -32px; }
.icon-new    { background-position: 0 -64px; }
.icon-save   { background-position: 0 -96px; }

Sprites

Magic Selectors

img/player/play.png
img/player/play_active.png
img/player/play_hover.png
@import "player/*.png";
@include all-player-sprites;

.button-play {
  @include player-sprite(play);
}

Sprites

.player-sprite, .player-play, .player-play_pause {
  background: url('/images/player-sc690ad66a4.png') no-repeat;
}
.player-play {
  background-position: 0 -110px;
}
.player-play:hover, .player-play.play_hover, .player-play.play-hover {
  background-position: 0 0;
}
.player-play:active, .player-play.play_active, .player-play.play-active {
  background-position: 0 -55px;
}

Sprites

Sprite-Layout Configuration

$player-layout: horizontal;

Sprites

Sprite-Layout Configuration

$player-layout: diagonal;
  
$player-layout: smart;
  

Sprites

$player-spacing: 100px // add more space between sprite images
@import "player/*.png"
@include all-player-sprites;

.button-play {
  @include player-sprite(play);
  height: player-sprite-height(play);
  width: player-sprite-width(play);
}
  

Sprites

Styling file downloads

img/fileicons/jpg.png
img/fileicons/doc.png
img/fileicons/zip.png
img/fileicons/pdf.png
img/fileicons/xml.png
img/fileicons/txt.png
@import "fileicons/*.png";
@include all-fileicons-sprites;
$icons: sprite-map("fileicons/*.png"); // point to sprite-map

@each $sprite-name in sprite-names($icons) {
  a[href $=".#{$sprite-name}"] {
    padding-left: 25px;
  }
}

Sprites

Sprites configuration variables

$<map>-spacing           - space in px around the sprites
$<map>-repeat            - whether to repeat the sprite bg
$<map>-position          - the x position of the sprite on the map
$<map>-sprite-base-class - the base class (default ".<map>-sprite")
$<map>-clean-up          - whether to delete old image maps
$<map>-<sprite>-spacing  - spacing, for individual sprites
$<map>-<sprite>-repeat   - repeat, for individual sprites
$<map>-<sprite>-position - position, for individual sprites

Example:

$sprites-header_bg-repeat: repeat-x;

.addtolibrary {
  +sprite-background-position($tracks-sprites, track_addtolibrary, 5px, 50%)
}

 

Retina Sprites

$sprites: sprite-map("sprites/*.png");
$sprites-retina: sprite-map("sprites-retina/*.png");
@mixin sprite-background($name) {
  background-image: sprite-url($sprites);
  background-position: sprite-position($sprites, $name);
  background-repeat: no-repeat;
  display: block;
  height: image-height(sprite-file($sprites, $name));
  width: image-width(sprite-file($sprites, $name));
  @media (-webkit-min-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 3/2), (min-device-pixel-ratio: 2) {
    @if (sprite-position($sprites, $name) != sprite-position($sprites-retina, $name)) {
      $ypos: round(nth(sprite-position($sprites-retina, $name), 2) / 2);
      background-position: 0 $ypos;
    }
    // Hard coded width of the normal sprite image. There must be a smarter way to do this.
    @include background-size(444px auto);
    background-image: sprite-url($sprites-retina);
  }
}

// Usage
.mail-icon {
  @include sprite-background(mail);
}

Sprites

useful additions: disable asset caching

rename generated Sprite image

# config.rb
asset_cache_buster :none

# Rename the generated sprite images
on_sprite_saved do |filename|
  if File.exists?(filename)
    FileUtils.mv filename, filename.gsub(%r{-s[a-z0-9]{10}\.png$}, '.png')
  end
end

# Replace in stylesheets generated references to sprites
# by their counterparts without the hash uniqueness.
on_stylesheet_saved do |filename|
  if File.exists?(filename)
    css = File.read filename
    File.open(filename, 'w+') do |f|
      f << css.gsub(%r{-s[a-z0-9]{10}\.png}, '.png')
    end
  end
end
  

Compass Plugins

Github List of Compass Plugins

loading Compass plugins

add to the config.rb

# config.rb
...
require 'rgbapng'
require 'compass-bootstrap'

RGBAPNG Plugin

https://github.com/aaronrussell/compass-rgbapng

$ sudo gem install compass-rgbapng
@import "rgbapng";
.box {
  @include rgba-background(rgba(0,0,0,0.75));
}
.box {
  background: url('/images/rgbapng/000000bf.png?1282127952');
  background: rgba(0, 0, 0, 0.75); }

Compass plugins

Responsive Grid Plugin – Susy

$ sudo gem install compass-susy-plugin
$ compass create myproject -r susy -u susy
    
.page {
  @include container;
  @include susy-grid-background;
}
    

Thanks for your attention!

Sven Wolfermann | maddesigns

 

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