Des CSS

kick-ass

avec Sass





Sass,

 C'est kick-ass POUR ...

    variables


    // Entier
    $integer : 5;
    
    // Booléen
    $boolean : true;
    
    // Mesure
    $length  : 15px;
    
    // Couleur
    $color   : #BADA55;
    
    // Chaine de caractères
    $string  : 'images/ma-super-image.jpg';

    Nesting


    .ma-liste {
        float: left;    a {
            display: block;        &:hover, &:focus {
                text-decoration: none;
            }
        }
    }

    CSS

    .ma-liste { float: left; }
    .ma-liste a { display: block; }
    .ma-liste a:hover, 
    .ma-liste a:focus { text-decoration: none; }


    http://thesassway.com/beginner/the-inception-rule

    Fonctions


    @function ma-fonction($a, $b, $c) {
        @return ($a + $b) / $c;
    }
    .mon-element {
        width: ma-fonction(120px, 20px, 2);   
    }

    CSS

    .mon-element {
        width: 70px;
    }

    Mixins


    @mixin mon-mixin($a) {
        border: 1px solid rgba(0, 0, 0, .1);
        color: white;
        background: deepskyblue;
        text-align: $a;
    }
    .mon-element {
        @include mon-mixin(center);
    }

    CSS

    .mon-element {
        border: 1px solid rgba(0, 0, 0, .1);
        color: white;
        background: deepskyblue;
        text-align: center;
    }

    Gestion des couleurs


    $color   : #2ecc71;
    $lighten : lighten($color, 15%); // #208e4e
    $darken  :  darken($color, 15%); // #69dd9a
    $transp  :    rgba($color,  .5); // rgba(46, 204, 113, 0.5)

    • $color

    • $lighten

    • $darken

    • $transp

    http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html

    Concatenation des fichiers


    Multiples fichiers côté développement.


    /* styles.scss */ 
    @import "modules"; // _module.scss
    @import "helpers"; // _helpers.scss
    @import "reset";   // _reset.scss
    @import "main";    // _main.scss


    Un seul fichier en production.


    ... le responsive web design, 

    les architectures modulaires, 

    les calculs, les namespaces,

    le café, la vaisselle ...

    ALLER PLUS LOIN 

    QUE 3 VARIABLES 

    ET 2 MIXINS

    @extend & classes abstraites


    %clearfix:after {
        content : '';
        display : table;
        clear   : both;
    }
    .float-container {
        @extend %clearfix;
    }

    CSS

    .float-container:after {
        content : '';
        display : table;
        clear   : both;
    }

    Messages en pagaille


    Erreur, merci de faire quelque chose !

    Tout est OK, veuillez circuler.

    Vous devriez peut-être faire attention.

    Petite information...

    %message {
        border: 1px solid;
        font-weight: bold;
    }
    
    .message-error {
        @extend %message;
        border-color :  darken(red,  5%);
        color        :  darken(red, 15%);
        background   : lighten(red, 40%);
    }
        
    .message-ok {
        @extend %message;
        border-color :  darken(green,  5%);
        color        :  darken(green, 15%);
        background   : lighten(green, 40%);
    }
    
    .message-warn {
        @extend %message;
        border-color :  darken(orange,  5%);
        color        :  darken(orange, 15%);
        background   : lighten(orange, 40%);
    }
    
    .message-error, .message-ok, .message-warn {
        border: 1px solid;
        font-weight: bold;
    }
    
    .message-error {
        color: #b30000;
        background: #ffcccc;
        border-color: #e60000;
    }
        
    .message-ok {
        color: #003400;
        background: #4dff4d;
        border-color: #006700;
    }
    
    .message-warn {
        color: #b37300;
        background: #ffedcc;
        border-color: #e69500;
    }
    

    REM, le graal du font-sizing



    calculs & fallbacks



    @mixin rem($value, $base: 16) {
      font-size: $value + px;
      font-size: $value / $base + rem;
    }
    
    .mon-element { @include rem(24); }

    CSS

    .mon-element {
        font-size: 24px;   /* Internet Explorer 8 */
        font-size: 1.5rem; /* Autres navigateurs  */
    }

    Conditionner le rendu


    @mixin rem($value, $base: 16) {    @if $support-ie8 {
            font-size: $value + px; 
        }    font-size: $value / $base + rem;
    }
    
    $support-ie8: false;
        
    .mon-element { @include rem(24); }
    

    CSS

    .mon-element { font-size: 1.5rem; }
    


    http://hugogiraudel.com/2013/03/18/ultimate-rem-mixin/

    Vite, en position !

     
    @mixin pos($top, $right, $bottom, $left, $position: absolute) {
        top      : $top;
        right    : $right;
        bottom   : $bottom;
        left     : $left;
        position : $position;
    }
    .element { @include pos(1em, .5em, auto, auto); }

    CSS

    .element {
       position: absolute;
       top: 1em;
       right: 0.5em;
       bottom: auto;
       left: auto;
    }

    Les perfs, toujours les perfs


    Moins de lignes générées...


    @mixin pos($top, $right, $bottom, $left, $position: absolute) {
        @if    $top != auto { top    : $top }
        @if  $right != auto { right  : $right }
        @if $bottom != auto { bottom : $bottom }
        @if   $left != auto { left   : $left }
        position : $position;
    }


    ... plus vite la page est chargée !


    https://github.com/thoughtbot/bourbon/blob/master/app/assets/stylesheets/addons/_position.scss

    Media queries pour les nuls


    One mixin to rule them all


    @mixin mq($size) {
        @if $size == small {
            @media (max-width: 48em) { @content; }
        }
        @if $size == medium {
            @media (max-width: 58em) { @content; }
        }
        @if $size == large {
            @media (min-width: 68em) { @content; }
        }
    }


    http://css-tricks.com/media-queries-sass-3-2-and-codekit/

    RetiNa na na na na !


    @mixin mq($size) {
        /* ... */
        
        @if $size == retina {
          @media  
            only screen and (-webkit-min-device-pixel-ratio: 1.3),
            only screen and (min-resolution: 124.8dpi),
            only screen and (min-resolution: 1.3dppx) { 
              @content;                 
            }
        }
    }


    https://github.com/kaelig/hidpi

    BOOM !


    .element {
        background: url('my-awesome-background.jpg');
        width: 50%;
        float: left;
        
        @include mq(small) {
            width: 100%;
            float: none;
        }
        
        @include mq(retina) {
            background: url('my-awesome-background-high-def.jpg');
        }
    }

    Terminé.


    .element {
        background: url('my-awesome-background.jpg');
        width: 50%;
        float: left;
    }
    
    @media (max-width: 48em) {
        .element {
            width: 100%;
            float: none;
        }
    }
    
    @media  
        only screen and (-webkit-min-device-pixel-ratio: 1.3),
        only screen and (min-resolution: 124.8dpi),
        only screen and (min-resolution: 1.3dppx) { 
        .element {
            background: url('my-awesome-background-high-def.jpg');
        }
    }

    grilles & frameworks



    1KB GRID, 960 GRID SYSTEM, BLUEPRINT, Columnal, CSSWIZARDRY GRIDS, FEM CSS, FLEXGRID, FLUIDABLE, FOUNDATION, FRAMELESS, Golden Grid, GRIDSET, GROUNDWORK, GUMBY, HELIUM, JUSTIFYGRID, Knacss, KUBE, LESS FRAMEWORK, ONE% CSS GRID, Responsive Grid System, RWDGRID, SASS GRID, SUSY, TWITTER BOOTSTRAP SCAFFOLDING, UNSEMANTIC, xCSS, Zen Grids...

    Une grille RESPONSIVE simple


    .header { @include cols(6) }
    @
    include
    {
    cols
    (1)
    }
    .footer { @include cols(6) }


    http://css-tricks.com/dont-overthink-it-grids/

    15 lignes.


    $nb-columns   : 6;
    $wrap-width   : 1140px;
    $column-width : 180px;
    
    $gutter-width : ($wrap-width - $nb-columns * $column-width) / $nb-columns;
    $column-pct   : percentage($column-width / $wrap-width);
    $gutter-pct   : percentage($gutter-width / $wrap-width);
    @mixin cols($cols) {
      width: $column-pct * $cols + $gutter-pct * ($cols-1);
      margin-right: $gutter-pct;
      float: left;
    
      @media screen and (max-width: 400px) {
        width: 100%; 
        margin-right: 0;
      }
    }

    CSS counters + Sass = epicwin


    10 lignes de code.


    body {
      counter-reset: ct1 ct2 ct3 ct4 ct5 ct6;     // Initialisation
    }
    
    $nest: ();
    
    @for $i from 1 through 6 {                    // Boucle
      h#{$i} {
        counter-increment: ct#{$i};               // Incrémentation
      
        &:before {
          content: $nest counter(ct#{$i}) ". ";   // Affichage
        }
      }
      $nest: append($nest, counter(ct#{$i}) "."); // Concaténation
    }

    "Mixinifier" tout ça


    @mixin numbering($from: 1, $to: 6) {  counter-reset : ct1 ct2 ct3 ct4 ct5 ct6;
      $nest         : ();  @if $from >= 1 and $to <= 6 {
        @for $i from $from to $to+1 {      h#{$i} {
            counter-increment: ct#{$i};
            &:before { 
              content: $nest counter(ct#{$i}) ". " 
            }
          }      $nest: append($nest, counter(ct#{$i}) ".");
        }
      }
    }
    
    body {
      @include numbering(1, 4);
    }
    

    Kaelig STAMP OF APPROVAL !


    Foreach, la boucle oubliée


    $kiwiparty: 
      "accessibilité",
      "ergonomie",
      "nouveautés technologiques", 
      "conformité aux standards";
    
    @each $item in $kiwiparty {
      // $item
    }
    


    La même chose, JS style !

    @for $i from 1 through length($kiwiparty) {
      // nth($kiwiparty, $i)
    }

    La puissance des Listes imbriquées


    $pages : 
      "home"     "bg-home.jpg", 
      "about"    "about.png", 
      "products" "prod_bg.jpg", 
      "contact"  "assets/contact.jpg";
    
    @each $page in $pages {
        $selector : nth($page, 1);
        $path     : nth($page, 2);
        
        .#{ $selector } body {
            background: url('../images/#{ $path }');
        }
    }
    

    CSS

    .home     body { background: url('../images/bg-home.jpg'); }
    .about    body { background: url('../images/about.png'); }
    .products body { background: url('../images/prod_bg.jpg'); }
    .contact  body { background: url('../images/assets/contact.jpg'); }
    

    Menu "actif" 

    sans JS / server-side



    Méthode 1 : output dans une boucle


    $pages : home, about, products, contact;
    
    @each $item in $pages {
        .#{ $item } .nav-#{ $item } { 
            style: awesome;
        }
    }

    CSS

    .home     .nav-home     { style: awesome; }
    .about    .nav-about    { style: awesome; }
    .products .nav-products { style: awesome; }
    .contact  .nav-contact  { style: awesome; }

    Méthode 2 : création d'un sélecteur



    $pages    : home, about, products, contact;
    $selector : ();
    
    @each $item in $pages {
        $selector: append($selector, unquote(".#{$item} .nav-#{$item}"));
    }
    
    #{ $selector } { 
        style: awesome; 
    }
    

    CSS

    .home     .nav-home, 
    .about    .nav-about,
    .products .nav-products, 
    .contact  .nav-contact {
        style: awesome;
    }

    Merci !


    Hugo Giraudel
    CSS Goblin, Sass hacker, margin psycho
    hugogiraudel.com
    @hugogiraudel
    Made with Slides.com