# framR (Saffron)

Frontend Development Toolkit 

Author: **Sascha Fuchs**

Date: ** 09.05.2012**

# Voraussetzungen

Saffron setzt vorwiegend auf Compilersprachen mit denen CSS, HTML und Javascript generiert wird, was die Pflege und Wartung des Codes verbessert. Es ist auch eines der Konzepte, da alle Sourcefiles im `lib/` Verzeichniss gelagert werden, während der Kompilierte Code in das `app/` Verzeichniss wandert (das Verzeichniss das man am Ende ausliefern muss)

- `lib/jade`   => app/*.html
- `lib/sass`   => app/components/css/*.css
- `lib/coffee` => app/components/js/*.js


**Wichtig! Es ist zwingend erforderlich mit den Quellfiles zu arbeiten!**

Wer bislang noch kein [RUBY][1] oder [Node.js][2] auf seiner Entwicklungsumgebung installiert hat, sollte dies nun nachholen, da beide Umgebungen zwingend erforderlich sind. Mac Nutzer können die Ruby Installation ausklammern, da es auf ihrem System schon vorinstalliert vorliegt.

> Für Mac User ist es einfacher mittels [Homebrew][3] Node.js und NPM  installieren. 

Desweiteren ist die Installation der Compilersprachen erforderlich, das ganze lässt sich einfach über das Terminal erledigen.

### SASS installieren 
_RUBY - pre version_ 

[SASS][4] ist das Superset für CSS, womit man mit Variablen und Logischen Elementen CSS kompilieren lassen kann. Da SASS ständig weiterentwickelt wird, ist es auch die mächtigste und flexibleste Compilersprache.

``` bash
gem install sass --pre
``` 

### Compass installieren 
_RUBY - pre version_

[Compass][5] ist ein Metaframework das auf SASS aufsetzt. Mittels Compass entfält die Eingabe von CSS3 Prefixen, es beinhaltet weiterhin eine Dynamische Pfadangabe zu Fonts und Images sowie Spritegenerierung.

``` bash
gem install compass --pre
```

### Coffeescript installieren 
_NODE_

[Coffeescript][6] ist eine Compilersprache für Javascript.

``` bash
npm install -g coffee-script
``` 

### Jade installieren 
_NODE_

[JADE][7] ist eine Compilersprache mit deren Hilfe HTML generiert wird. Jade bedient sich einer sehr kurzen und lesbaren Syntax, kann zusätzlich mit Partials und Blockelementen (instanzierung) arbeiten.

``` bash
npm install jade
```

Zum Abschluss noch den Package Manager Bower und den Javascript Taskrunner Grunt: 

### Grunt installieren 
_NODE_

[Grunt][8] ist das Herzstück des Frameworks, man kann es als Taskmanager ansehen womit die verschiedenen Prozesse (Initialisierung, Verteilung, Überwachung und Build) gestartet werden.

``` bash
npm install -g grunt-cli
```

### Bower installieren 
_NODE_

[Bower][9] dient als Package Manager für Webprojekte, womit über einfache Terminal Commands JS Pakete von Github geladen und installiert werden.

``` bash
npm install -g bower
``` 

### Font Converter 
_Brew_

Möchte man über Grunt Iconfonts erstellen muss man die entsprechenden Converter installieren:

``` bash
brew install fontforge ttfautohint
brew install https:*//raw.github.com/sapegin/grunt-webfont/master/Formula/sfnt2woff.rb*
```

Das liest sich jetzt eventuell nach recht vielen Installationen, man sollte aber nicht vergessen das man sämtliche Tools auch für andere Projekte benutzen kann. 

### Installation schlägt fehl

Falls die Installationen der Gems oder Node Packages fehl schlagen sollte man mit `SUDO` arbeiten.

``` bash
sudo npm install ...
sudo gem install ...
```


# Grundlagen

Inner und Außerhalb des Frameworks gilt die Namingconvention die sich durch das gesamte Development einer Webseite oder App zieht. 


## OOCSS

Auch wenn Objekt Orientierte Programmierung sich nicht 100% für CSS umsetzten lässt, sind einige Prinzipien miteingeflossen, die dafür sorgen sollen das sich die Styles, durch die Modularisierung wesentlich einfacher übertragen lassen.

### Basics

Zur Veranschaulichung ein einfaches Beispiel:

``` markup
<ul class="menu">
    <li><a href="#">link</a></li>
    <li><a href="#">link</a></li>
    <li><a href="#">link</a></li>
    <li><a href="#">link</a></li>
</ul>
```

Und so würde man das Listen Element in SASS Stylen:

``` scss
.menu
    list-style: none
    margin-bottom: 0
    li
        border-bottom: 1px solid #777
        a
            display: block
            line-height: 20px
            font-size: 14px
            color: #999
            background: #eee
            &:hover
                background: #ddd
                color: #222
```

Das wäre der herkömmliche Weg, nur würde man jetzt die HTML Struktur ändern, würde der Style womöglich nicht mehr funktionieren.

``` markup
<dl class="menu">
    <dt><a href="#">link</a></dt>
    <dt><a href="#">link</a></dt>
    <dt><a href="#">link</a></dt>
    <dt><a href="#">link</a></dt>
</dl>
```

Das Styling würde jetzt nicht mehr greifen, wir müssten es an die neuen Strukturellen Elemente anpassen.

``` scss
.menu
    dt
        border-bottom: 1px solid #777
        a
            display: block
            line-height: 20px
            font-size: 14px
            color: #999
            background: #eee
            &:hover
                background: #ddd
                color: #222
```

Ein weiteres Problem wäre wenn man den Style für die Link Elemente anderweitig benutzen möchte. Es bleibt einem nichts anderes übrig als das Styling zu kopieren.

Gemäß den Prinzipien von OOCSS ist jedes Element über die Klasse anzusprechen. Damit würde unsere Struktur wie folgt aussehen:

``` markup
<ul class="menu">
    <li class="menu--item">
        <a href="" class="menu--button">link</a>
    </li>
    <li class="menu--item">
        <a href="" class="menu--button">link</a>
    </li>
    <li class="menu--item">
        <a href="" class="menu--button">link</a>
    </li>
</ul>
```

Jetzt können wir jedes Element gezielt über Klassenaufruf ansprechen und gegebenfalls Stile auch an andere Elemente übertragen.

``` scss
.menu
    list-style: none
    margin-bottom: 0
.menu--item
    border-bottom: 1px solid #777
.menu--button
    display: block
    line-height: 20px
    font-size: 14px
    color: #999
    background: #eee
    &:hover
        background: #ddd
        color: #222
``` 

Anstatt für das Menu jetzt noch ein eigenes Link Element zu generieren, kann man auch auf schon bestehende Klassen für z.B. Buttons zugreifen:

``` markup
<ul class="menu">
    <li class="menu--item">
        <a href="#" class="btn bnt--primary btn--normal">link</a>
    </li>
    <li class="menu--item">
        <a href="#" class="btn bnt--primary btn--normal">link</a>
    </li>
    <li class="menu--item">
        <a href="#" class="btn bnt--primary btn--normal">link</a>
    </li>
</ul>
```


Die Regel jedes Element in Klassen überzuführen ist aber nicht zwingend, wenn man möchte kann man auch auf die Kaskade zugreifen und damit Listenelemente Stylen:

``` markup
<ul class="menu">
    <li><a href="#" class="btn">link</a></li>
    <li><a href="#" class="btn">link</a></li>
    <li><a href="#" class="btn">link</a></li>
    <li><a href="#" class="btn">link</a></li>
</ul>
```

In dem Fall sollte man die Verschachtelung nicht über 5 Ebenen führen und mit dem Child Selector arbeiten.

``` scss
.menu
    list-style: none
    margin-bottom: 0
    > li
        border-bottom: 1px solid #777
```

### Verwendung von Selektoren

Um Elemente über CSS zu selektieren werden Klassen genutzt, in Ausnahmen können auch HTML Tags genutzt werden (z.B. für Text Inhalt den ein Kunde später mit einem Editor einpflegen kann). Ein striktes Verbot gilt für die Verwendung von IDs. Diese sind immer einzigartig im Dokument und daher nicht für die Modularisierung verwendbar. 

#### Klassen Selektoren

Ein CSS Selektor startet immer mit dem Block zu dem er gehört. Der Block kann über einen _modifier_ abgeleitetet und damit modifiziert werden.

``` css
.block
.block_modifier
.block--element
.block--element_modifier
``` 

Child Elemente innerhalb des Block werden mit --element gekennzeichnet.  Elemente können ebenso mit einem _modifier_ abgeleitet werden.

Grundsätzlich gilt, das CSS Selektoren sich immer auf Klassen beziehen die zudem immer klein geschrieben werden.

#### JS Selektoren

Für Javascript Selektoren ist die Regelung gelockert, das heißt es können auch IDs verwendet werden. 

Um Elemente über Javascript zu selektieren, sollten eigene Selektoren verwendet werden. Eine Ausnahme wäre das aktivieren von Styling Änderungen, ansonsten sollte der selektor immer unabhängig von CSS sein. 

Vorteilhaft wäre es wenn man JS Selektoren mit einem "j" im Namen kenntlich macht:

`<div class="unit--10 colum jMySelector">...</div>`

Ansonsten kann man auch IDs verwenden, wenn sie die Funktion von z.B. Fragment identifier nicht behindern.

## SCSS - SASS

Sass kommt mit zwei Syntax Varianten daher, die man nach gutdünken nutzen kann. Kickstarter wurde durchgehend in der SASS Syntax programmiert, das ganze aus einem Grund: **Es tippt sich einfach schneller**. Und auch angenehmer da man verschachtelte Stylingblöcke wesentlich einfacher verschieben kann, man nicht auf Semikolons achten muss ebenso entfallen die geschweiften Klammern (bis auf einige Ausnahmen). Mixins werden nicht mit `@include mixin-name` sondern mit `+mixin-name` aufgerufen. Das ganze hat aber einen kleinen Nachteil, die Lesbarkeit des Codes leidet etwas, wobei das nicht das größte Manko sein sollte, vorrausgesetzt man ist nicht Dokumentationsscheu.

``` scss
@mixin font-size($size, $is-important: false) {
  @if $is-important {
    font-size: $size + px !important;
    font-size: ($size / 10) + rem !important;
  } @else {
    font-size: $size + px;
    font-size: ($size / 10) + rem;
  }
} 
.myclass {
  @include font-size(10); 	} 	  
```

Und jetzt das ganze noch einmal mit der SASS Syntax:

``` scss
@mixin font-size($size, $is-important: false)
  @if $is-important
    font-size: $size + px !important
    font-size: ($size / 10) + rem !important
  @else
    font-size: $size + px
    font-size: ($size / 10) + rem

.meineklasse
  +font-size(10)
```

Es besteht aber kein Zwang zur SASS Syntax, wer auch weiterhin mit geschweiften Klammern arbeiten will (dafür nicht mehr auf Whitespaces aufpassen muss), kann auch die SCSS Syntax verwenden. Die `style.sass` muss dann in `style.scss` umbenannt werden, dann kann man in der SCSS Syntax schreiben.

## Mixins

Fast alles Mixins die ich geschrieben habe, werden zusätzlich über Variblen gesteuert, zum Teil für interne Berechnungen oder zum Freischalten zusätzlicher Stylingdeklarationen. Um die Aufrufe so einfach wie möglich zu gestalten, wurden die Eingangsvariablen mit Defaultwerten angefüllt - dies trifft aber nicht auf jede Eingangsvariable zu.

``` scss
+fontface($filename, $fontname: $filename, $fontweight: normal, $fontstyle: normal)
```

Am Beispiel des Fontface Mixins sieht man das es nur eine Variable ohne Defaultwert gibt, was in diesem Fall auch Sinn macht, geht es ja um das Laden einer Font. Der Name der Fontfamily ergibt sich aus dem `$filename`, bräuchte man demnach auch nicht selbst einstellen. Das Fontweight und der Fontstyle sind ebenso voreingestellt. Wenn man damit einverstanden ist das der Dateiname der Font auch gleichzeitig der Font-Family Name wird, kann man den Aufruf auch abkürzen:

``` scss
+fontface($filename: meinefont)
```

Innerhalb der Klammern `(...)` spricht man von einer Liste, befüllt mit Keyword Arguments und den dazugehörigen Variablen. Beim Kompilieren wird diese Liste einfach von links nach rechts eingelesen, die Wertezuordnung ist im eigentlichen Mixin festgelegt worden (nicht im Aufruf). Theoretisch benötigt man daher keine Keyword Arguments und kann den Aufruf noch weiter abkürzen.

``` scss
+fontface(meinefont)
```

Solange man sich jetzt an die Reihenfolge der Wertezuordnung hält - die im Mixin festgelegt wurden - kann man auf die Keywords verzichten. Setzt natürlich voraus das man die Reihenfolge kennt und so kann man den Aufruf abkürzen. Das ganze hat natürlich einen Nachteil es ist schlechter lesbar weil wesentlich Kryptischer, zum Teil aber auch umständlicher.

``` scss
+fontface(meinefont, meinefont, normal, italic)
```

Nehmen wir jetzt an ich will eigentlich nur den Dateinamen übergeben und den Stil auf `italic` umstellen, ohne Keywords ist man gezwungen alle Werte zu übergeben. Überspringen geht dann nicht: 

``` scss
+fontface(meinefont, , , italic) // FAIL!
+fontface(meinefont, italic) // FAIL!
```

Je nachdem wie viele Variablen das Mixin nun benötigt kann das zum einem recht Fehleranfällig werden (wenn man versehentlich ein Listenelement übersprungen hat) zum anderen muss man die Reihenfolge eben genau kennen. In diesem Fall ist es einfacher, man benutzt die Keywords um die Variablen gezielt mit Werten zu füllen.

``` scss
+fontface($filename: meinefont, $fontstyle: italic)
```

### Mixins einbinden

Mixins können in der Regel direkt in das Stylesheet eingebunden werden, vorrausgesetzt das Mixin bringt eine eigene Klasse mit. In dem Fall wird die Klasse und das Styling in das CSS kompiliert. Liegt aber keine Klasse vor, zum Beispiel bei den Textshadow Mixins muss das Mixin mit einem Selektor verschachtelt werden.

``` scss
// Mixin ohne eigene Klase
@mixin simple-border($width:1, $direction: 0, $blur:3, $trans: 0.3)
  border: ($width + 0px) solid #fff
  +box-shadow(0 ($direction + 0px) ($blur + 0px) rgba(0,0,0,$trans))

// Der Aufruf muss daher mit einem Selektor verschachtelt werden
.meinebox
  +simple-border
``` 

Es gibt aber auch Mixins die bringen ihre eigenen Klassen schon mit, entweder weil man davon ausgeht das man das Mixin so oder so nur einmal global einbinden wird, oder weil Javascripte die Klassennamen als Referenz benötigen.

``` scss
// Mixin mit eigener Klasse
@mixin message-box($radius: 0, $font-size: $body-font-size)
  .message-box
    +font-size($font-size - 1)
    @if $radius > 0
      $radius: $radius + 0px
      +border-radius($radius)
      ...

// Der Aufruf ist einfach
+message-box
```

Will man jetzt die Message Boxen in zwei unterschiedlichen Stilen in das CSS kompilieren lassen, geht das nicht mehr über den direkten Aufruf, da sich die Stile dann einfach überschreiben würden. Das umgeht man in dem man das Mixin wieder in eine eigene Klasse aufruft - es ist dann darauf zu achten das die `mobile.sass` und andere Javascripte den Selektornamen direkt aufrufen.

``` scss
.site-header
  +message-box(.......) 
.site-content
  .news-article
    +message-box(anderer Stil)
```

### Mixins Stylen

Die Mixins liefern im groben schon alle nötigen Stylingvarianten die man benötigen würde, es ist jedoch klar das man dabei nicht alle erdenklichen Möglichkeiten abfragen könnte. Ansonsten hätte man unzählige Variablen die man befüllen müsste und dann wird es mit Sicherheit immer noch etwas geben was einem fehlt.

Um das gelieferte Styling nachzustylen oder zu verfeinern ist es daher Ratsam dies auf die Normale Art zu tun. Heißt wir rufen das Mixin auf und stlyen die Punkte einfach noch mal nach.

``` scss
.site-header
  +message-box(.......)
  .message-box
    // Zusätzliche Stylings
    display: inline-block
    position: absolute
    ...
```

Es gibt einige Mixins in die ich mit `@content` einen zusätzlichen Platzhalter integriert habe, damit werden die zusätzlichen Stile direkt in den Style des Mixins geschrieben.

``` scss
@mixin flex-breakpoint($value: 768, $dir: max)
  // with two values media queries with min and max
  @if length($value) == 2
    $max: nth($value,2) + 0px
    $min: nth($value,1) + 0px
  @media only screen and (min-width: $min) and (max-width: $max)
    @content   

// Mixin Aufruf und hinzufügen der weiteren Stile
.site-header
  height: 200px
  +flex-breakpoint(768)
    display: none
``` 

## Ampersand

Das Ampersand `&` Zeichen benutzt man in der Regel um in einem Nesting Block auf den übergeordneten Selektor zu referenzieren.

``` scss
// SASS
.selector
  width  : 200px
  height : 20px
  &:hover
    background: red
  &.combineClass
    margin-left: 10px
    &:first-child
        margin-left: 0
        a
            display: block
            &:hover
                color: #fff
                background: #14C2BA
& + .adjacentSelector 
    position: relative
& > .childSelector
    position: absolute
.descendantSelector 
    background: black
```

``` css
/* CSS */
.selector {
  width: 200px;
  height: 20px; }
.selector:hover {
  background: red; }
.selector.combineClass {
  margin-left: 10px; }
.selector.combineClass:first-child {
  margin-left: 0; }
.selector.combineClass:first-child a {
  display: block; }
.selector.combineClass:first-child a:hover {
  color: white;
  background: #14c2ba; }
.selector + .adjacentSelector {
  position: relative; }
.selector > .childSelector {
  position: absolute; }
.selector .descendantSelector {
  background: black; }
```

So wird es in der Regel am häufigsten Benutzt, aber man kann Ampersand auch für den umgekehrten Fall benutzen.

``` scss
// SASS
.meineklasse
  width: 200px
  height: 20px
  display: inline-block
  .lt-ie7 &
    display: inline
```

``` css
/* CSS */
.meineklasse {
  width: 200px;
  height: 20px;
  display: inline-block; }

.lt-ie7 .meineklasse {
  display: inline; }
``` 
Das macht jetzt bei dem kurzen Codebeispiel vermutlich nicht viel Sinn, aber gehen wir einen Schritt weiter und stellen uns eine Dropdown Navigation über drei Ebenen vor. In der dritten Navigationsebene muss ein Link für den Internet Explorer anders gestylt werden.

``` scss
nav#mainnav
  ul
    list-style-type: none
    margin-bottom: 0
    overflow: hidden
    li
        float: left
        height: 30px
        line-height: 30px
        padding: 0 10px
        a 
            background: #fff
            color: $blue
            &:hover
                background: $blue
                color: #fff
        ul
            width: 300px
            li
                display: block
                width: 100%
                a
                    +fontsize(12)
                li
                    a
                        background: rgba($blue,0.4)
                        &:hover
                            background: #fff
```

Sicherlich könnte man das auch wesentlich einfacher verschachteln, aber es soll als Beispiel dienen. Wie angesprochen wollen wir den Link der letzten Ebene für IE6 anders stylen. In der "normalen" Methode müssen wir den kompletten Selektor Baum nachbauen oder wir tippen die Selektoren einfach in eine Reihe zusammen - hält man sich nicht an die Reihenfolge wird CSS den Stil auch nicht wirklich überschreiben, da die Deklaration unterschiedliche Dominieren.

``` scss
nav#mainnav
  ul
    list-style-type: none
    margin-bottom: 0
    overflow: hidden
    li
        float: left
        height: 30px
        line-height: 30px
        padding: 0 10px
        a 
            background: #fff
            color: $blue
            &:hover
                background: $blue
                color: #fff
        ul
            width: 300px
            li
                display: block
                width: 100%
                a
                    +fontsize(12)
                li
                    a
                        background: rgba($blue,0.4)
                        &:hover
                            background: #fff
``` 

// Überschreiben in dem man den Nesting Baum kopiert (eventuell um weitere Stile hinzuzufügen)

``` scss
.lt-ie7
  nav#mainnav
    ul
        li
            ul
                li
                    li
                        a
                            background: lighten($blue, 10)
``` 

``` scss	
// Überschreiben als One Liner
.lt-ie7 nav#mainnav ul li ul li li a 
  background: lighten($blue, 10)
``` 

Je tiefer die Elemente verschachtelt werden desto umständlicher wird das über schreiben, da man im herkömmlichen Weg ohne Ampersand, den ganzen Nesting Baum kopieren müssen um eventuell eine einzige Anweisung zu geben.

``` scss
nav#mainnav
  ul
    list-style-type: none
    margin-bottom: 0
    overflow: hidden
    li
        float: left
        height: 30px
        line-height: 30px
        padding: 0 10px
        a 
            background: #fff
            color: $blue
            &:hover
                background: $blue
                color: #fff
        ul
            width: 300px
            li
                display: block
                width: 100%
                a
                    +fontsize(12)
                li
                    a
                        background: rgba($blue,0.4)
                        .lt-ie7 &
                            background: lighten($blue, 10)
                        &:hover
                            background: #fff
``` 

Über den Weg erspart man sich die kopiererei und das beste, man bleibt auch weiterhin im betroffenen Nesting Block.

## Extend

Mittels `@extend` kann man Selektoren miteinander verbinden und behält dabei wesentlich besser die Kontrolle, da sich die Erweiterung auch einfach wieder deaktivieren lassen - ohne das man erst in einem Berg von Selectoren den entsprechenden erst finden muss um ihn zu löschen.

``` scss
// SASS
.meineklasse 
  width: 200px
  height: 20px

.andereklasse
  background: red
  @extend .meineklasse
``` 

``` css
/* CSS */
.meineklasse, .andereklasse {
  width: 200px;
  height: 20px; }

.andereklasse {
  background: red; }
``` 

Das wäre der sogenannte Idealfall, häufig kommt es aber vor das man eigentlich nur einen Teilabschnitt einer Klasse benötigen würde (z.B. nur die Width). Das geht mit `@extend` auf diesem Wege jedoch nicht, dafür benötigt man eine dritte Klasse in der die wiederholbaren Anweisungen ausgelagert werden.

``` scss
// SASS
.binbreit
  width: 200px

.meineklasse 
  height: 20px
  @extend .binbreit

.andereklasse
  background: red
  @extend .meineklasse
  @extend .binbreit
```

``` css
/* CSS */
.binbreit, .meineklasse, .andereklasse {
  width: 200px; }

.meineklasse, .andereklasse {
height: 20px; }

.andereklasse {
background: red; }
``` 

Das ist jetzt nicht völlig Elegant, wenn die Klasse `.binbreit` sonst keine andere Funktion erfüllt, war aber bislang der beste Lösungsweg. 

``` scss
// SASS
%binbreit
  width: 200px

.meineklasse 
  height: 20px
  @extend %binbreit

.andereklasse
  background: red
  @extend .meineklasse
  @extend %binbreit
``` 

``` css
/* CSS */
.meineklasse, .andereklasse {
  width: 200px; }

.meineklasse, .andereklasse {
  height: 20px; }

.andereklasse {
  background: red; }
``` 

Gut jetzt könnte man auch sagen das sieht nicht sonderlich Elegant aus, da wir die zwei oberen Blöcke nicht zusammengefasst haben. Das Codebeispiel zeigt eigentlich ganz gut das `@extend` fast schon overdone ist. 

Extend ist sinnvoll wenn es um komplexe Stylinganweisungen geht, die eine Menge an Codezeilen benötigen, womit man Code einsparen kann.


[1]:	http://rubyinstaller.org/
[2]:	http://nodejs.org/
[3]:	http://mxcl.github.io/homebrew/
[4]:	http://sass-lang.com
[5]:	http://compass-style.org
[6]:	http://coffeescript.org/
[7]:	http://jade-lang.com/
[8]:	http://gruntjs.com/
[9]:	http://bower.io/
[10]:	http://gruntjs.com/plugins
[11]:	https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei
[12]:	http://macrabbit.com/slicy/
[13]:	http://danielmall.com/articles/svg-workflow-for-designers/
[14]:	https://github.com/filamentgroup/grunticon

[image-1]:	colum.png
[image-2]:	container.png
[image-3]:	grid.png