Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Work & Play with Compass and SASS

Work & Play with Compass and SASS

Still there are some controversies about whether precompiling CSS is a good or a bad idea. Sometimes this leads to fights, struggles and name-calling. This talk is almost clean of it.

I'll show examples of "SASS" and "Compass"" from his day-to-day work and what you can do if you unleash the power of preprocessing.

Andreas Dantz

April 25, 2012
Tweet

More Decks by Andreas Dantz

Other Decks in Programming

Transcript

  1. y
    Work & Play
    (Verantwortungsvolles) Arbeiten mit SASS & Compass

    View Slide

  2. Andreas Dantz
    0
    @dantz — [email protected]

    View Slide

  3. CSS zu kompilieren ist total bescheuert,
    unnötig und führt zu minderwertigen
    Ergebnissen. Wer so etwas nutzt, schlägt auch
    wehrlose Omas auf der Straße.
    Andreas Dantz, anno 2009

    View Slide

  4. CSS 2.1
    flickr.com/photos/thomasbrauner

    View Slide

  5. CSS 3
    h p://www.flickr.com/photos/bcnbits/

    View Slide

  6. .css
    .sass
    .scss

    View Slide

  7. CSS
    .box {
    margin: 1em;
    }
    .box .content {
    border: 1px solid #f00;
    }

    View Slide

  8. SASS
    .box
    margin: 1em
    .content
    border: 1px solid #f00

    View Slide

  9. SCSS
    .box {
    margin: 1em
    .content {
    border: 1px solid #f00;
    }
    }

    View Slide

  10. Variablen
    1
    erste Schri e in Richtung Programmiersprache

    View Slide

  11. $color-main: #00aeef;
    $baseline: 16px;
    strong { color: $color-main; }
    p { margin-bottom: $baseline; }
    SCSS
    strong { color: #00aeef; }
    p { margin-bottom: 16px; }
    CSS

    View Slide

  12. 4px + 4px;
    4px - 4px;
    4px * 2;
    4px / 2;
    8px;
    0px;
    8px;
    2px;
    SCSS
    CSS

    View Slide

  13. halbe Grundlinie als Margin
    halbe Grundlinie abzüglich
    Rahmen als Padding

    View Slide

  14. $baseline: 32px;
    $border-width: 4px;
    .box {
    border: $border-width solid $color-main;
    margin: $baseline / 2;
    padding: $baseline / 2 - $border-width;
    }
    SCSS
    .box {
    border: 4px solid #00aeef;
    margin: 16px;
    padding: 12px;
    }
    CSS

    View Slide

  15. round(4.3);
    ceil(4.2);
    floor(4.6);
    abs(-12);
    percentage(120/960);
    SCSS
    4;
    5;
    4;
    12;
    12,5%;
    CSS

    View Slide

  16. $color-main: #00aeef;
    a { color: $color-main; }
    a:hover,
    a:focus { color: lighten($color-main, 15%); }
    SCSS
    a { color: #00aeef; }
    a:hover,
    a:focus {
    color: #3dcaff;
    }
    CSS

    View Slide

  17. adjust-hue($color, $degrees)
    lighten($color, $amount)
    darken($color, $amount)
    saturate($color, $amount)
    desaturate($color, $amount)
    grayscale($color)
    complement($color)
    invert($color)
    SCSS

    View Slide

  18. @if
    @for
    @each
    @while
    SCSS

    View Slide

  19. View Slide

  20. SCSS
    @import "compass/reset","compass/css3";
    @import "layout";
    // ============== Vars =====================
    $items: 6; // number of items
    $arc: 90; // arc of the circle
    $angle: $arc/$items; // angle between items
    $space:170; // a value in pixel. It's the space between the red circle and the items
    $circleCenterX: 30; // the X coord of the red circle center
    $circleCenterY: 30; // the Y coord of the red circle center
    $disappearDelay: 50;
    // Generate items position + keyframes animation
    @for $i from 1 through $items {
    // I'm not really good in math, so I suppose that they have a better way to calcul coordinates :)
    $rad: ( $angle * ($i - 1) + $angle/2 ) * (pi()/180);
    $x:round(($circleCenterX + $space) * cos($rad) );
    $y:round(-($circleCenterY + $space) * sin($rad) );
    // Coords for the rebound during the animation
    $xm: round($x * 1.15);
    $ym: round($y * 1.15);
    $disappearDelay: $disappearDelay * 1.35;
    // CSS checkbox + label tricks
    #menu:checked ~ .items li:nth-child(#{$i}) {
    -webkit-animation-name: "appear-'#{$i}'";
    -webkit-animation-duration: 240ms;
    -webkit-animation-iteration-count: 1;
    -webkit-animation-fill-mode: forwards;
    -webkit-animation-delay: (20 * $i)+ms;
    }
    #menu:not(:checked) ~ .items li:nth-child(#{$i}) {
    -webkit-animation-name: "disappear-'#{$i}'";
    -webkit-animation-duration: (320 + $disappearDelay)+ms;
    -webkit-animation-iteration-count: 1;
    -webkit-animation-fill-mode: forwards;
    }
    h ps://github.com/Victa/path-menu

    View Slide

  21. und andere Sauerein mit Selektoren
    Nesting
    2

    View Slide

  22. View Slide

  23. .box {
    margin: 12px;
    h2 {
    font-size: $baseline * 2;
    }
    }
    SCSS
    .box {
    padding: 12px;
    }
    .box h2 {
    font-size: 64px;
    }
    CSS

    View Slide

  24. article {
    header, footer { background-color: $color-main; }
    }
    SCSS
    article header, article footer {
    background-color: #00aeef;
    }
    CSS

    View Slide

  25. $color-main: #00aeef;
    a {
    color: $color-main;
    &:hover,
    &:focus { color: lighten($color-main, 15%); }
    }
    SCSS
    a { color: #00aeef; }
    a:hover, a:focus {
    color: #3dcaff;
    }
    CSS

    View Slide

  26. button {
    color: #fff;
    background: linear-gradient(top,
    $color-main 0%, darken($color-main, 5%) 100%);
    .no-cssgradients & { background: #eee };
    }
    SCSS
    button {
    background: linear-gradient(top,
    #00aeef 0%, #009bd5 100%);
    }
    .no-cssgradients button {
    background: #eee;
    }
    CSS

    View Slide

  27. flickr.com/photos/sharynmorrow/

    View Slide

  28. View Slide

  29. .message {
    background-color: lighten($color-main, 40%);
    border: $border-width solid $color-main;
    h3 {
    font-size: $baseline / 2;
    }
    p:last-child { margin-bottom: 0; }
    }
    .error {
    @extend .message;
    background-color: lighten($color-error, 40%);
    border-color: $color-error;
    }
    SCSS

    View Slide

  30. .message, .error {
    background-color: #bcedff;
    border: 4px solid #00aeef;
    padding: 1em;
    margin-bottom: 32px;
    }
    .message h3, .error h3 {
    font-size: 16px;
    margin-bottom: 16px;
    }
    .message p:last-child, .error p:last-child {
    margin-bottom: 0;
    }
    .error {
    background-color: #ffcccc;
    border-color: red;
    }
    CSS

    View Slide

  31. flickr.com/photos/basibanget

    View Slide

  32. #page-wrapper #page #main-wrapper #main #content,
    #page-wrapper #main .column#content,
    .section .region #block-system-main.block {
    font-weight: bold;
    h2.active, h2, .visuallyhidden {
    color: #fff;
    a, .button {
    &:link, &:visited { background-color: #f00 }
    &:hover, &focus { #background-color: #f0f; }
    }
    }
    }
    SCSS

    View Slide

  33. #page-wrapper #page #main-wrapper #main #content,
    #page-wrapper #main .column#content,
    .section .region #block-system-main.block {
    font-weight: bold;
    }
    #page-wrapper #page #main-wrapper #main #content h2.active, #page-wrapper #page #main-wrapper #main #content h2, #page-wrapper #page #main-wrapper #main #content .visuallyhidden,
    #page-wrapper #main .column#content h2.active,
    #page-wrapper #main .column#content h2,
    #page-wrapper #main .column#content .visuallyhidden,
    .section .region #block-system-main.block h2.active,
    .section .region #block-system-main.block h2,
    .section .region #block-system-main.block .visuallyhidden {
    color: #fff;
    }
    #page-wrapper #page #main-wrapper #main #content h2.active a:link, #page-wrapper #page #main-wrapper #main #content h2.active a:visited, #page-wrapper #page #main-wrapper #main #content
    h2.active .button:link, #page-wrapper #page #main-wrapper #main #content h2.active .button:visited, #page-wrapper #page #main-wrapper #main #content h2 a:link, #page-wrapper #page #main-wrapper #main
    #content h2 a:visited, #page-wrapper #page #main-wrapper #main #content h2 .button:link, #page-wrapper #page #main-wrapper #main #content h2 .button:visited, #page-wrapper #page #main-wrapper #main
    #content .visuallyhidden a:link, #page-wrapper #page #main-wrapper #main #content .visuallyhidden a:visited, #page-wrapper #page #main-wrapper #main #content .visuallyhidden .button:link, #page-wrapper
    #page #main-wrapper #main #content .visuallyhidden .button:visited,
    #page-wrapper #main .column#content h2.active a:link,
    #page-wrapper #main .column#content h2.active a:visited,
    #page-wrapper #main .column#content h2.active .button:link,
    #page-wrapper #main .column#content h2.active .button:visited,
    #page-wrapper #main .column#content h2 a:link,
    #page-wrapper #main .column#content h2 a:visited,
    #page-wrapper #main .column#content h2 .button:link,
    #page-wrapper #main .column#content h2 .button:visited,
    #page-wrapper #main .column#content .visuallyhidden a:link,
    #page-wrapper #main .column#content .visuallyhidden a:visited,
    #page-wrapper #main .column#content .visuallyhidden .button:link,
    #page-wrapper #main .column#content .visuallyhidden .button:visited,
    .section .region #block-system-main.block h2.active a:link,
    .section .region #block-system-main.block h2.active a:visited,
    .section .region #block-system-main.block h2.active .button:link,
    .section .region #block-system-main.block h2.active .button:visited,
    .section .region #block-system-main.block h2 a:link,
    .section .region #block-system-main.block h2 a:visited,
    .section .region #block-system-main.block h2 .button:link,
    .section .region #block-system-main.block h2 .button:visited,
    .section .region #block-system-main.block .visuallyhidden a:link,
    .section .region #block-system-main.block .visuallyhidden a:visited,
    .section .region #block-system-main.block .visuallyhidden .button:link,
    .section .region #block-system-main.block .visuallyhidden .button:visited {
    background-color: #f00;
    }
    #page-wrapper #page #main-wrapper #main #content h2.active a:hover, #page-wrapper #page #main-wrapper #main #content h2.active a focus, #page-wrapper #page #main-wrapper #main #content
    h2.active .button:hover, #page-wrapper #page #main-wrapper #main #content h2.active .button focus, #page-wrapper #page #main-wrapper #main #content h2 a:hover, #page-wrapper #page #main-wrapper #main
    #content h2 a focus, #page-wrapper #page #main-wrapper #main #content h2 .button:hover, #page-wrapper #page #main-wrapper #main #content h2 .button focus, #page-wrapper #page #main-wrapper #main
    #content .visuallyhidden a:hover, #page-wrapper #page #main-wrapper #main #content .visuallyhidden a focus, #page-wrapper #page #main-wrapper #main #content .visuallyhidden .button:hover, #page-wrapper
    #page #main-wrapper #main #content .visuallyhidden .button focus,
    #page-wrapper #main .column#content h2.active a:hover,
    #page-wrapper #main .column#content h2.active a focus,
    #page-wrapper #main .column#content h2.active .button:hover,
    #page-wrapper #main .column#content h2.active .button focus,
    #page-wrapper #main .column#content h2 a:hover,
    #page-wrapper #main .column#content h2 a focus,
    #page-wrapper #main .column#content h2 .button:hover,
    #page-wrapper #main .column#content h2 .button focus,
    #page-wrapper #main .column#content .visuallyhidden a:hover,
    #page-wrapper #main .column#content .visuallyhidden a focus,
    #page-wrapper #main .column#content .visuallyhidden .button:hover,
    #page-wrapper #main .column#content .visuallyhidden .button focus,
    .section .region #block-system-main.block h2.active a:hover,
    .section .region #block-system-main.block h2.active a focus,
    .section .region #block-system-main.block h2.active .button:hover,
    .section .region #block-system-main.block h2.active .button focus,
    .section .region #block-system-main.block h2 a:hover,
    .section .region #block-system-main.block h2 a focus,
    .section .region #block-system-main.block h2 .button:hover,
    .section .region #block-system-main.block h2 .button focus,
    .section .region #block-system-main.block .visuallyhidden a:hover,
    .section .region #block-system-main.block .visuallyhidden a focus,
    .section .region #block-system-main.block .visuallyhidden .button:hover,
    .section .region #block-system-main.block .visuallyhidden .button focus {
    #background-color: #f0f;
    }
    CSS

    View Slide

  34. Die drei Legitimationen fürs Nesting in SASS
    1. Ich möchte mehr Übersicht in meinem
    Stylesheet
    2. Ich hä e die Selektoren auch manuell in
    CSS kombiniert
    3. Ich will mir Tipparbeit sparen

    View Slide

  35. Ordnung scha Ordnung
    Architektur
    3

    View Slide

  36. application.scss
    _base.scss
    _layout.scss
    _menu.scss
    _mixins.scss

    View Slide

  37. @include "base";
    @include "mixins";
    @include "layout";
    @include "menu";

    keine Ausgabe!

    View Slide

  38. jetzt bin ich offiziell CSS-Programmierer
    Mixins
    4

    View Slide

  39. @mixin link-effect {
    color: $color-main;
    &:hover, &:focus {
    color: darken($color-main, 30%); }
    }
    nav a { @include link-effect; }
    SCSS
    nav a {
    color: #00aeef;
    }
    nav a:hover, nav a:focus {
    color: #003f56;
    }
    CSS

    View Slide

  40. Mixins sollst Du nur benutzen,
    wenn Parameter übergeben.
    Sonst wirst das Stylesheet Du beschmutzen,
    kannst du damit wirklich leben?

    View Slide

  41. @mixin border-radius($radius) {
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    border-radius: $radius;
    }
    .box { @include border-radius(5px); }
    SCSS
    .box {
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
    }
    CSS

    View Slide

  42. @mixin linkcolor($link:black, $hover:red) {
    color: $link;
    &:hover, a:focus { color: $hover; }
    }
    a { @include linkcolor($hover:yellow); }
    SCSS
    a { color: black; }
    a:hover, a:focus { color: yellow; }
    CSS

    View Slide

  43. View Slide

  44. @mixin linkcolor($dark: false) {
    @if $dark == true {
    color: black;
    &:hover { color: blue; }
    } @else {
    color: white;
    &:hover { color: #ccc; }
    }
    }
    a { @include linkcolor(); }
    a.alt { @include linkcolor(true); }
    SCSS
    a { color: white; }
    a:hover { color: #ccc; }
    a.alt { color: black; }
    a.alt:hover { color: blue; }
    CSS

    View Slide

  45. sonspring.com/journal/sass-for-designers

    View Slide

  46. 5

    View Slide

  47. @import "compass";
    .box {
    @include border-radius(8px);
    @include background(linear-gradient(#000, #333));
    }
    SCSS
    .box {
    -moz-border-radius: 8px;
    -webkit-border-radius: 8px;
    -ms-border-radius: 8px;
    border-radius: 8px;
    background: -webkit-gradient(linear, 50% 0%, 50% 100%,
    color-stop(0%, #000000), color-stop(100%, #333333));
    background: -webkit-linear-gradient(#000000, #333333);
    […]
    background: linear-gradient(#000000, #333333);
    }
    CSS

    View Slide

  48. header {
    background: image-url('logo.jpg');
    h1 {
    width: image-width('logo.jpg');
    height: image-height('logo.jpg');
    }
    }
    SCSS
    header {
    background: url('/images/logo.jpg?1321202172');
    }
    header h1 {
    width: 346px;
    height: 400px;
    }
    CSS

    View Slide

  49. .unlocked {
    background: inline-image('unlocked.png');
    }
    SCSS
    .unlocked {
    background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAABkCAMAAACxdeD
    +AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/
    eHBhY2tldCBiZWdpbj0i77u/
    IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIF
    hNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8v
    d3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi
    8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0
    dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYW
    NpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODVBQkU5NzQ1NjU1MTFFMUFGODdFNTI1QzQwQzYzNkMiIHhtcE1NOkRvY3VtZW50SUQ9
    InhtcC5kaWQ6ODVBQkU5NzU1NjU1MTFFMUFGODdFNTI1QzQwQzYzNkMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLm
    lpZDowQjAyREI0RDU2NEUxMUUxQUY4N0U1MjVDNDBDNjM2QyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowQjAyREI0RTU2NEUxMUUxQUY4N0U1
    MjVDNDBDNjM2QyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/
    Pvv5YQwAAACEUExURcvLy/Pz87CwsImJic/Pz/v7++Tk5K+vr62trd3d3YCAgLGxsaKiot/f38rKyri4uPf398fHx/
    Dw8Pj4+LW1tenp6ZaWlqurq66uroODg8jIyIuLi5ycnIqKiu/v7/r6+oWFhZubm9jY2KampuHh4ZiYmNLS0tnZ2YSEhH9/f7Kysv///
    3IN8QsAAACqSURBVHja7NXnDoIwFAXgikXcey/cem7f//2sDV3E8EdRY3qTNvTLpaeEEJh4Uizgn2L/
    clxucziZAlgdPIzXaA8SbIYu1nCOhZiDuXhFIuduk1xsIHr0L2YKO0zVGHueihNxhXXoulXMOSOD1XLRpu8s8hZl1Rv9+tuUh3yls4zbP7bnd4NC
    +vvSySAZVGs76U55rYfdU3+v5AXlLEv3rfiJKPw7CvAuwAAQmUbpoWRiDAAAAABJRU5ErkJggg==');
    }
    CSS

    View Slide

  50. flickr.com/photos/runningdevine

    View Slide

  51. @import "icon/*.png";
    @include all-icon-sprites($dimensions:true);
    SCSS
    .icon-sprite, .icon-plus, .icon-minus {
    background: url('/images/icon-sd55776.png');
    no-repeat;
    }
    .icon-plus {
    background-position: 0 0;
    height: 14px;
    width: 24px;
    }
    .icon-minus {
    background-position: -15px 0;
    height: 7px;
    width: 24px;
    }
    CSS

    View Slide

  52. das Chaos beherrschen
    Responsive
    6

    View Slide

  53. @media screen and (min-width: 480px) {
    nav li {
    float: none;
    }
    }

    View Slide

  54. $break-phone: 320px;
    nav li {
    float: left;
    @media screen and (max-width: $break-phone + 1) {
    float: none;
    }
    }
    SCSS
    nav li {
    float: left;
    }
    @media screen and (max-width: 321px) {
    nav li {
    float: none;
    }
    }
    CSS

    View Slide

  55. #blow {
    @include border-radius(50%);
    background-color: $color-main;
    }
    @for $i from 1 through 500 {
    @media screen and (min-width: $break-phone + $i) {
    #blow {
    width: #{600 - $i}px;
    height: #{600 - $i}px;
    }
    }
    }
    SCSS

    View Slide

  56. […]
    @media screen and (min-width: 335px) {
    #blow {
    width: 585px;
    height: 585px; } }
    @media screen and (min-width: 336px) {
    #blow {
    width: 584px;
    height: 584px; } }
    @media screen and (min-width: 337px) {
    #blow {
    width: 583px;
    height: 583px; } }
    @media screen and (min-width: 338px) {
    #blow {
    width: 582px;
    height: 582px; } }
    @media screen and (min-width: 339px) {
    #blow {
    width: 581px;
    height: 581px; } }
    @media screen and (min-width: 340px) {
    #blow {
    width: 580px;
    height: 580px; } }
    […]
    CSS

    View Slide

  57. $break-small: 320px;
    $break-large: 1024px;
    @mixin respond-to($media) {
    @if $media == mobile {
    @media only screen and (max-width: $break-mobile) { @content; }
    }
    @else if $media == medium {
    @media only screen and (min-width: $break-mobile + 1)
    and (max-width: $break-large - 1) { @content; }
    }
    @else if $media == widescreen {
    @media only screen and (min-width: $break-large) { @content; }
    }
    }
    SCSS
    .avatar {
    border: 1px solid $color-main;
    @include respond-to(mobile) { width: 100% ;}
    @include respond-to(medium) { width: 150px; }
    @include respond-to(widescreen) { float: none; }
    }

    View Slide

  58. .avatar {
    border: 1px solid #00aeef;
    }
    @media only screen and (max-width: 320px) {
    .avatar {
    width: 100%;
    }
    }
    @media only screen and (min-width: 321px) and (max-width: 1023px) {
    .avatar {
    width: 150px;
    }
    }
    @media only screen and (min-width: 1024px) {
    .avatar {
    float: none;
    }
    }
    CSS

    View Slide

  59. woher? wie? wie viel?
    Workflow
    7

    View Slide

  60. View Slide

  61. CodeKit

    View Slide

  62. TEAMWORK
    flickr.com/photos/runningdevine

    View Slide

  63. Fragen?
    Danke
    8

    View Slide