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