SassROMPENDO OS (VÁRIOS) LIMITES DO CSS COM
+ Compass
ALCIDES QUEIROZ
+ Compass
ALCIDES QUEIROZ
ROMPENDO OS (VÁRIOS) LIMITES DO CSS COM
+
ALCIDES QUEIROZ
ROMPENDO OS (VÁRIOS) LIMITES DO CSS COM
+
ALCIDES QUEIROZ
/alcidesqueiroz
/alcidesqueiroz
/alcidesqueiroz
goo.gl/0HSUA4
ROMPENDO OS (VÁRIOS) LIMITES DO CSS COM
ALCIDES QUEIROZ
Just install it:
goo.gl/48fowWROMPENDO OS (VÁRIOS) LIMITES DO CSS COM
O PROBLEMA
OS PROBLEMAS
OS PROBLEMAS
ORGANIZAÇÃO
REUSO
COMPLETAMENTE LOGICLESS
VERBOSO
IMPORTS PROBLEMÁTICOS
SASS
O que é?
Pré-processador CSS criado em 2007 por Hampton
Catlin
SASS E SCSS
Sintaxe identada
#main
color: blue
font-size: 0.3em
a
font:
weight: bold
family: serif
&:hover
background-color: #EEE
COMPILANDO
sass --update .
sass --update --no-cache .
sass --update --no-cache .:..\\CSS
sass --watch --no-cache .:..\\CSS
sass --watch --no-cache --poll .:..\\CSS
COMENTÁRIOS
//Comentário inline
/*
Comentário
Em
Bloco
*/
ANINHAMENTO DE SELETORES
CSS
body {
background-color: #FF0;
}
body > header {
width: 900px;
}
body > header h1 {
font-weight: normal;
}
ANINHAMENTO DE SELETORES
SCSS
body {
background-color: #FF0;
> header{
width: 900px;
h1{
font-weight: normal;
}
}
}
ANINHAMENTO DE SELETORES
SCSS
body, #wrapper {
background-color: #FF0;
> header{
width: 900px;
h1{
font-weight: normal;
}
}
}
ANINHAMENTO DE SELETORES
CSS Gerado
body, #wrapper {
background-color: #FF0;
}
body > header, #wrapper > header {
width: 900px;
}
body > header h1, #wrapper > header h1 {
font-weight: normal;
}
NÃO ABUSE!
SIGA A REGRA DOS 4 NÍVEIS
(&) REFERENCE SELECTOR
h1, h2 {
&:before{
margin-right: 10px;
}
.standout {
color: red;
}
&.title{
font-weight: bold;
}
}
(&) REFERENCE SELECTOR
h1:before, h2:before {
margin-right: 10px;
}
h1 .standout, h2 .standout {
color: red;
}
h1.title, h2.title {
font-weight: bold;
}
CSS Gerado
LET’S CODE!
VARIÁVEIS
$base-color: #679;
color: $base-color;
$default-border-radius: 3px;
border-radius: $default-border-radius;
VARIÁVEIS - A FLAG !default
$base-color: #679;
$base-color: #444;
Agora, o valor de $base-color é #444
VARIÁVEIS - A FLAG !default
$base-color: #679;
$base-color: #444 !default;
O valor de $base-color é #679
VARIÁVEIS - OUTROS USOS
SELETORES
$button-icon-selector: “.btn button .icon:before”;
VARIÁVEIS - OUTROS USOS
PROPRIEDADES COMPLEXAS
$default-border: dotted 2px #444;
$strange-shadow: 7px 7px 5px rgba(50, 50, 50, 0.75),
-10px 5px 20px #444;
VARIÁVEIS - OUTROS USOS
EM CONJUNTO COM OUTRAS VARIÁVEIS
$default-border-style: dotted;
$default-border-color: #222;
$default-border-width: 2px;
$default-border: $default-border-style
$default-border-color $default-border-width;
VARIÁVEIS - OUTROS USOS
ETC...
$default-transition-duration: 300ms;
$mask-opacity: 0.7;
$default-label-separator: ‘:’;
LET’S CODE!
INTERPOLAÇÃO
$side: left;
$border: "solid 1px #000";
.nome-de-classe-#{$side}{
text-align: $side;
float: #{$side};
border-#{$side}-width: 1px;
border-top: $border;
border-right: #{$border};
}
INTERPOLAÇÃO
.nome-de-classe-left {
text-align: left;
float: left;
border-left-width: 1px;
border-top: "solid 1px #000"; /*ops...*/
border-right: solid 1px #000;
}
CSS Gerado
IMPORTANDO
@import ‘variables’;
IMPORTANDO - CSS VS SCSS
//Os 4 imports abaixo são imports convencionais do CSS
@import "main.css";
@import "boleto" print;
@import "http://teste.com/layout.css";
@import url("font-face.css");
/* O import abaixo não possui extensão CSS, nem é
definido via url(), não inicia com "http://" ou possui
uma media query, portanto o Sass tentará localizar um
arquivo .SCSS ou .SASS equivalente*/
@import ‘variables’;
IMPORTANDO - @import ANINHADO
Exemplo.scss
.top-bar{
.user{
color: #000;
}
}
Exemplo2.scss
#main{
@import ‘exemplo’;
}
IMPORTANDO - @import ANINHADO
#main .top-bar .user {
color: #000;
}
CSS Gerado
PARTIALS
_variables.scss
ORGANIZANDO
variáveis
mixins
componentes
dependências do compass
font-face
layout
ANINHAMENTO DE PROPRIEDADES
CSS
.profile{
border-left: solid 1px #000;
border-right: dotted 4px #FF0;
}
ANINHAMENTO DE PROPRIEDADES
SCSS
.profile{
border:{
left: solid 1px #000;
right: dotted 4px #FF0;
}
}
ANINHAMENTO DE PROPRIEDADES
SCSS
.profile{
border: dashed 2px #00F {
left: solid 1px #000;
right: dotted 4px #FF0;
}
}
LET’S CODE!
Sass INTERACTIVE
sass -i
DIRETIVA @debug$largura-padrao: 260px;
$largura-total: $largura-padrao * 2;
@debug "Largura total: #{$largura-total}";
TIPOS DE DADO
números
2.5, 20, 40px, 50deg, 600ms
strings
sans-serif, “exemplo”, ‘h1+h2’
cores
black, #ABCDEF, rgba(0, 0, 100, 1)
booleans
true e false
Strings são sempre traduzidas
de forma literal, a não ser em
interpolações, onde strings
“quoted” perdem suas aspas.
TIPOS DE DADO
nulls
null
listas (listas de valores separados por espaço ou vírgula)
10px 10px 15px 10px
double 5px #FDD;
"Lucida Grande", Tahoma, Verdana, Arial, sans-serif
10px 12px, 20px 40px
Uma lista de listas... =)
(10px 12px), (20px 40px)igual a
A flag !default considera variáveis null
como não-definidas, e as reescreve
OPERADORES MATEMÁTICOS
+ soma
- subtração
* multiplicação
/ divisão
OPERADORES MATEMÁTICOS
$altura: 50px * 3 + 400px;
$angulo: 30deg * 4;
$duracao: 400ms * 5;
$largura: ($tamanho-padrao * $quantidade) +
($espacamento-padrao * ($quantidade – 1)) +
($espacamento-padrao / 2);
OPERADORES MATEMÁTICOS
O curioso caso do operador /
font: 20pt/40pt; /*Isso não é uma
divisão*/
width: 50px/2; //Isso também não...
width: (50px/2); /*Isso SIM é uma
divisão*/
$largura: 50px/2; //Isso também
width: 50px/2+1; //E isso...
OPERADORES DE COMPARAÇÃO
> maior que
< menor que
>= maior ou igual que
<= menor que ou igual
== igual a
!= diferente de
OPERADORES DE COMPARAÇÃO
$exemplo: 10 > 6 and (4 > 5 or 3 == 3);
$exemplo2: 20 != 30;
$exemplo3: $b >= 18;
OPERADORES LÓGICOS
not
and
or
OPERADORES LÓGICOS
$exemplo: (true and false) or true;
$exemplo2: not $habilitar-animacoes;
DIRETIVAS DE CONTROLE @if, @else,
@else if
$inverse-color: true;
…
.introduction{
background-color: $base-color;
@if $inverse-color{
color: #FFF;
}
}
DIRETIVAS DE CONTROLE @if, @else,
@else if
@if $width == 'auto' {
//…
} @else if $width == 1 {
//…
} @else {
display: inline-block;
width: $width;
}
DIRETIVAS DE CONTROLE @if, @else,
@else if
@if $auto-resize and $largura > 300px{
//…
} @else if not $auto-resize {
//…
} @else {
//…
}
DIRETIVA DE CONTROLE @for
@for $i from 1 through 4 {
.nivel-#{$i} {
font-size: 20px + (12px / $i);
}
}
.nivel-1 { font-size: 32px; }
.nivel-2 { font-size: 26px; }
.nivel-3 { font-size: 24px; }
.nivel-4 { font-size: 23px; }
DIRETIVA DE CONTROLE @for
@for $i from 1 through 4 {
.nivel-#{$i} {
font-size: 20px + (12px / $i);
}
}
.nivel-1 { font-size: 32px; }
.nivel-2 { font-size: 26px; }
.nivel-3 { font-size: 24px; }
.nivel-4 { font-size: 23px; }
DIRETIVA DE CONTROLE @for
@for $i from 1 to 4 {
.nivel-#{$i} {
font-size: 20px + (12px / $i);
}
}
.nivel-1 { font-size: 32px; }
.nivel-2 { font-size: 26px; }
.nivel-3 { font-size: 24px; }
DIRETIVA DE CONTROLE @while
$i: 1;
@while $i <= 5 {
.nivel-#{$i} { text-indent: 1cm * $i; }
$i: $i + 1;
}
.nivel-1 { text-indent: 1cm; }
.nivel-2 { text-indent: 2cm; }
.nivel-3 { text-indent: 3cm; }
.nivel-4 { text-indent: 4cm; }
.nivel-5 { text-indent: 5cm; }
DIRETIVA DE CONTROLE @each
@each $carro in chevette, opala, kadett {
.detalhes-#{$carro} {
background-image: url('/images/#{$carro}.png');
}
}
.detalhes-chevette{ background-image: url("/image/chevette.png");}
.detalhes-opala{ background-image: url("/image/opala.png");}
.detalhes-kadett{ background-image: url("/image/kadett.png");}
DIRETIVA DE CONTROLE @each
div{
$i: 2px;
@each $lado in top, right, left, bottom {
border-#{$lado}-width: $i;
$i:$i+2px
}
}
div {
border-top-width: 2px;
border-right-width: 4px;
border-left-width: 6px;
border-bottom-width: 8px;
}
OPERAÇÕES COM CORES
red + blue //=>#FF00FF
#234 * 3 //=>#6699CC
#DDD - #FF0 //=>#0000DD
#FFF / 10 //=> #191919
LET’S CODE!
HERANÇA - TENTATIVA 1
.profile{
border: solid 2px #222;
overflow: hidden;
color: #D22;
display: inline-block;
background-color: #FFF;
}
CSS
.corporative-profile{
border: solid 2px #222;
overflow: hidden;
color: #D22;
display: inline-block;
background-color: #DD2;
}
HERANÇA - TENTATIVA 1
Problemas desta abordagem:
Não é DRY
Manutenibilidade
HERANÇA - TENTATIVA 2
.profile,
.corporative-profile {
border: solid 2px #222;
overflow: hidden;
color: #D22;
display: inline-block;
background-color: #FFF;
}
CSS
.corporative-profile {
background-color: #DD2;
}
HERANÇA - TENTATIVA 2
Problemas desta abordagem:
Manutenibilidade: para caçar de quem um
determinado seletor herda
Manutenibilidade - parte 2: Os seletores filhos poluem
o seletor da regra base:
.profile,.corporate-profile,.student-profile,
.consultant-profile,etc.
HERANÇA - TENTATIVA 3
.profile{
border: solid 2px #222;
overflow: hidden;
color: #D22;
display: inline-block;
background-color: #FFF;
}
.corporative-profile{
background-color: #DD2;
}
CSS + HTML
<div class=“profile
corporative-profile”>…</div>
HERANÇA - TENTATIVA 3
Problemas desta abordagem:
Não há clara relação de extensão no código CSS
Dificulta múltiplos níveis de herança
Uma certa transferência de lógica de
estilização para o HTML
HERANÇA - THE SASS WAY!!!
.profile{
border: solid 2px #222;
overflow: hidden;
color: #D22;
display: inline-block;
background-color: #FFF;
}
SCSS
.corporative-profile{
@extend .profile;
background-color: #DD2;
}
HERANÇA
.profile, .corporative-profile {
border: solid 2px #222;
overflow: hidden;
color: #D22;
display: inline-block;
background-color: #FFF;
}
.corporative-profile {
background-color: #DD2;
}
CSS Gerado
WTF?
Um deja vu!?!?
HERANÇA - DEJA VU...
• Sim, o código gerado é igual ao da
tentativa 2.
• O único e grande problema da técnica
adotada era manutenibilidade
• Porém... você não precisa e nem deve manter o seu CSS gerado
• Preocupe-se apenas em manter um SCSS limpo,
manutenível, modularizado e fazer uso inteligente e
sensato dos seus seletores. Deixe a compilação com o Sass e descanse.
HERANÇA MÚLTIPLA
.detalhes{
border: dashed 3px #000;
}
.tile{
background-color: #2D2;
}
SCSS
.ficha{
@extend .detalhes;
@extend .tile;
color: #FFF;
}
HERANÇA MÚLTIPLA
.ficha{
@extend .detalhes, .tile;
color: #FFF;
}
Ou assim...
HERANÇA - ALÉM DE CLASSES
h1{
font-weight: normal;
font-family: OpenSans
Regular;
font-size: 30px;
}
#titulo{
text-transform: uppercase;
color: #222;
}
SCSS
h2{
@extend h1,
#titulo;
font-size: 20px;
}
HERANÇA - ALÉM DE CLASSES
h1, h2 {
font-weight: normal;
font-family: OpenSans Regular;
font-size: 30px;
}
#titulo, h2 {
text-transform: uppercase;
color: #222;
}
h2 {
font-size: 20px;
}
CSS Gerado
HERANÇA - SELETORES ANINHADOS
button{
&.general-button{
border-radius: 3px;
background-color: #22D;
}
}
.general-button{
color: #FFF;
}
SCSS
.dangerous-button{
@extend .general-button;
background-color: #D22;
}
HERANÇA - HERDANDO DO “NADA”
button{
@extend .essa-classe-nao-existe;
}
SCSS
<< Kaboom!
HERANÇA - A FLAG !OPTIONAL
button{
@extend .essa-classe-nao-existe !optional;
}
SCSS
HERANÇA - SELETORES ABSTRATOS
%teste{
color: blue;
}
.teste2{
@extend %teste;
font-weight:
normal;
}
.teste3{
@extend %teste;
font-weight: bold;
}
SCSS.teste{
color: blue;
}
.teste2{
@extend .teste;
font-weight:
normal;
}
.teste3{
@extend .teste;
font-weight: bold;
}
VS.
HERANÇA - SELETORES ABSTRATOS
.teste2, .teste3 {
color: blue;
}
.teste2 {
font-weight: normal;
}
.teste3 {
font-weight: bold;
}
CSS Gerado.teste, .teste2,
.teste3{
color: blue;
}
.teste2 {
font-weight: normal;
}
.teste3 {
font-weight: bold;
}
VS.
MIXINS
@mixin absolute-full-size{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
SCSS
.content{
@include absolute-full-size;
}
MIXINS
.content {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
CSS Gerado
MIXINS - PARÂMETROS
@mixin absolute-full-size($spacement){
position: absolute;
top: $spacement;
bottom: $spacement;
left: $spacement;
right: $spacement;
}
SCSS
.content{
@include absolute-full-size(10px);
}
MIXINS - PARÂMETROS COM VALOR
DEFAULT
@mixin absolute-full-size($spacement: 0){
position: absolute;
top: $spacement;
bottom: $spacement;
left: $spacement;
right: $spacement;
}
SCSS
.content{
@include absolute-full-size(10px);
}
MIXINS - PARÂMETROS NOMEADOS
@mixin tile-dimensions($horizontal-slots: 1,
$vertical-slots: 1){
width: $horizontal-slots * 120px;
height: $vertical-slots * 120px;
}
SCSS
.news-widget {
@include tile-dimensions($horizontal-slots: 3,
$vertical-slots: 2);
}.news-widget {
@include tile-dimensions($vertical-slots: 2,
$horizontal-slots: 3);
}
MIXINS - DIRETIVA @content
@mixin tile-center-icon{
.icon-center{
@content;
}
}
SCSS
.config-tile{
@include tile-center-icon{
@include fa-cogs; //Font-awesome icon…
}
}
MIXINS - QUANDO USAR?
@mixin absolute-full-size{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
SCSS
.content{
@include absolute-full-
size;
}
.absolute-full-size{
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.content{
@extend .absolute-full-
size;
}
VS.
MIXINS VS. EXTENDS
Mixins podem receber parâmetros Classes extendidas sempre se comportarão da mesma forma
Mixins precisam ser declarados antes de serem chamados
Extends devem ser usados para compartilhar estilos iguais entre regras
Mixins consiste em reaproveitamento de regras
Mixins consiste em reaproveitamento de regras e valores
Mixins não suportam referências cíclicas (mixin A inclui mixin B que inclui A)
Duas regras podem se estender mutuamente sem problema algum (apesar de não indicado)
Mixins devem ser usados para compartilhar estilos similares entre regras
Classes extendidas podem estar em qualquer lugar do código
MIXINS
Exemplo de mixins úteis.
FUNCTIONS
@function calcular($val: 5px) {
@return $val * 2;
}
margin-right: calcular(10px);
FUNCTIONS
@function tamanho-tile($slots: 1) {
$tamanho: $tamanho-padrao * $slots;
@if $espacamento-padrao > 0{
$tamanho: $tamanho + ($espacamento-padrao * $slots – 1);
}
@return $tamanho;
}
width: tamanho-tile(3);
height: tamanho-tile(2);
FUNCTIONS VS. MIXINS
Functions retornam um único valor Mixins não possuem retorno
Functions não podem conter propriedades CSS e obviamente nem regras. Elas apenas efetuam alguma espécie de processamento e retornam um resultado.
Mixins podem conter não apenas lógica (através das diretivas de controle), como propriedades CSS, ou até regras inteiras. As quais podem ser rederizadas nos pontos onde o mixin é chamado.
A declaração e a chamada de uma function exige parênteses. Independente de ela não possuir argumentos.
Mixins sem argumentos podem ser declarados e invocados sem parênteses
LET’S CODE!
FUNÇÕES NATIVAS - lighten
Ilumina uma cor
//Ilumina a cor preta em 10%
lighten(#000, 10)//=>#1A1A1A
A função lighten intensifica os três canais RGB
igualmente
FUNÇÕES NATIVAS - darken
Escurece uma cor
//Escurece a cor azul em 20%
darken(blue, 20)//=>#000099
A função darken reduz os três canais RGB
igualmente
FUNÇÕES NATIVAS - grayscale
Converte uma cor para a sua equivalente
em escala de cinza
grayscale(red)//=>#808080
FUNÇÕES NATIVAS - mix
Mistura duas cores de acordo com um peso
//Mistura as cores preto e branco
mix(black, white)//=>#7F7F7F
//Resulta em uma mistura com 10% de
//preto e 90% de branco
mix(black, white, 90)//=>#191919
Quanto mais alto o valor do peso, mais a cor
passada como segundo parâmetro irá predominar
na mistura.
FUNÇÕES NATIVAS - transparentize e
opacifyTorna uma cor transparente de acordo com
um determinado percentual
//Um azul 30% transparente, ou 70% opaco
transparentize(blue, 0.3)
A sua contrapartida é a função opacify
$cor: transparentize(blue, 1)
//Um azul 30% opaco, ou 70% transparente
opacify($cor, 0.3)
FUNÇÕES NATIVAS - scale-color
Cria uma nova cor com base em outra existente,
ajustando cada canal
//Aumenta os canais R e G em 10% e reduz o canal B em 20%
scale-color(blue, $red: 10%, $green: 10%, $blue: -20%)//=>#1919CC
http://goo.gl/F4BeyX
FUNÇÕES NATIVAS - if TERNÁRIO
Função que age de forma semelhante ao if
ternário em outras linguagens
//Se $dark-layout for true, $cor
//será #000
$cor: if($dark-layout, #000, #FFF);
$cor2: if(10 > 5 and 4 <= 7, #000, #FFF);
FUNÇÕES NATIVAS - unquote
Converte uma string quoted (com aspas) em
uma string sem aspas
$borda: “solid 1px #000”;
a { border: unquote($borda); } // a { border: solid 1px #000; }
A sua contrapartida é a função quote$carro: ferrari;
a { content: quote($carro); } // a { content: “ferrari”; }
FUNÇÕES NATIVAS - nth
Obtém um item de uma lista de acordo com
sua posição
$cor: nth(5px 5px 10px #FBD, 4);//#FBD
Listas em Sass são 1-based
FUNÇÕES NATIVAS - length
Retorna o tamanho de uma lista
$margens: 10px 5px 15px 0;
if(length($margens) > 0)... //length retorna 4
FUNÇÕES NATIVAS - index
Retorna a posição de um item em uma lista
$margens: 10px 5px 15px 0;
index($margens, 5px) //index retorna 2
FUNÇÕES NATIVAS - unit
Retorna a unidade de um valor numérico
unit(10px)//=> “px”
unit(120deg)//=> “deg”
unit(800ms)//=> “ms”
FUNÇÕES NATIVAS - unitless
Testa se um valor numérico possui unidade
@mixin tamanho-texto($tamanho){
@if(unitless($tamanho)){
$tamanho: "#{$tamanho}px";
}
font-size: unquote($tamanho);
}
h1{
@include tamanho-texto(30);
}
COMPASS config.rb
Retém todas as configurações do compass
# sass_path: the directory your Sass files are in. THIS file
should also be in the Sass folder
sass_path = File.dirname(__FILE__)
output_path = File.expand_path(File.join(sass_path, '../CSS'))
# css_path: the directory you want your CSS files to be.
css_path = output_path
# output_style = :expanded or :nested or :compact or :compressed
output_style = :expanded
http://goo.gl/JMm6Zh
ALT TAB...
http://goo.gl/YmQSez
COMPASS STATISTICS
Retorna estatísticas sobre um projeto compass
$ compass stats
SEGUINDO EM FRENTE...
Bourbon - http://bourbon.io
Compass Recipes - http://compass-recipes.moox.fr
Todas as funções do Sass - http://goo.gl/jdDkiE
DICAS ADICIONAIS...
BEM – Block, Element, Modifier - http://goo.gl/QpBJFo
Color Me - http://richbray.me/cms/usage/
Sassy Buttons - http://jaredhardy.com/sassy-buttons/
Normalize - http://goo.gl/kqpTv2