Por Ney Simões em 08/jan/2014
O pré-processador SASS, chegou ao ponto de ser considerado uma tecnoligia convencional. Hoje em dia quase ninguém desenvolve um front-end profissional usando o velho CSS, mas algumas pessoas que usam SASS (ou LESS) estão usando-o apenas para agrupar ou ter uma sintaxe melhor, porém como um CSS convencional. Sem aproveitar todo o poder que essas tecnologias proporcionam.
Esse é um resumo das três principais características do SASS e um apontamento das suas diferenças.
@mixin
Mixin é a característica mais conhecida do SASS. Ele permite criar umas espécie de função para compartilhar estilos semelhantes entre os seletores (bem, SASS também tem funções, porém não consigo encontrar palavra melhor no mundo). O caso de uso mais evidente é a de mixins que se aplicam aos prefíxos:@mixin border-radius($radius){
border-radius: $radius;
-o-border-radius: $radius;
-ms-border-radius: $radius;
-moz-border-radius: $radius;
-webkit-border-radius: $radius;
}
button{
@include border-radius(10px)
}
Mixins é a primeira característica que um iniciante usa ao aprender o SASS, mas é surpreendente como muitas vezes vejo usando da forma errada.
Por exemplo:@mixin rounded{
border-radius: 5px;
-o-border-radius: 5px;
-ms-border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
button{
@include rounded;
background: #ccc;
color: #222;
}
// Several lines down, in the same file, or even in another different file
//…
.simple-form input{
@include rounded;
}
.main-nav .item{
color: white;
a:hover, a:active {
@include rounded;
}
}
O que há de errado com isso? Não é DRY.
Este é o CSS gerado:
button{
border-radius: 5px;
-o-border-radius: 5px;
-ms-border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
background: #ccc;
color: #222;
}
.simple-form input{
border-radius: 5px;
-o-border-radius: 5px;
-ms-border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.main-nav .item{
color: white;
}
.main-nav .item a:hover, .main-nav .item a:active {
border-radius: 5px;
-o-border-radius: 5px;
-ms-border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
Vemos as exatas mesmas seis linhas repetidas no CSS várias vezes.
A regra de ouro de onde um mixin é uma boa escolha pode ser descrito em apenas uma linha:
Eles nos permitem […] compartilhar estilos semelhantes entre as regras.
A palavra chave é semelhantes.
Um mixin é utilizado para reutilizar regras, e não valores. Neste caso, para criar bordas arredondadas de raio diferente, mas se você escreve um mixin que não tem argumento, você está fazendo isso errado.
@extends
A diretiva @extends por outro lado, é primo estático do @mixin. Ele é projetado para compartilhar regras e valores entre seletores, evitanto repetições.
.rounded{
border-radius: 5px;
-o-border-radius: 5px;
-ms-border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
button{
@extend rounded
}
// Some lines down the road..
.simple-form input{
@extend .rounded;
}
.main-nav .item{
color: white;
a:hover, a:active {
@extend .rounded;
}
}
Desta vez, o CSS gerado se parece com isso:
.rounded, button, .simple-form input, .main-nav .item a:hover, .main-nav .item a:active{
border-radius: 5px;
-o-border-radius: 5px;
-ms-border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.main-nav .item{
color: white;
}
Ele tem apenas uma fração das linhas de abordage do @mixin, o que é bom porque um CSS mais leve significa um tempo de carregamento menor, especialmente com conexões lentas (celulares), e para o navegador também é muito mais eficiênte analisar uma regra aplicada em vários seletores, que aplicar a mesma regra uma vez para cada seletor.
Isto é impressionante porque, graças ao @extend nós podemos ter uma folha de estilo em SASS legível (você sabe, folhas de estilo dividas em vários arquivos, montar de forma que as mesmas regras se aplicam para as mesmas seções ou componentes do projeto, …) e, ao mesmo tempo ter otimizado o CSS (todos os seletores que possuem o mesmo pai são acorrentados a mesma regra, não importa em qual arquivo ou como conceitualmente independentes são) e, ao mesmo tempo, podemos manter limpo o nosso HTML porque não precisa adicionar classes específicas de regras como .rounded-border ou .highlighted-text que não tem significado do ponto de vista da aplicação.
Eu sei que algumas pessoas discordam sobre o que são classes no HTML, mas eu sou um grande fã de classes que uso para representar o que significa o elemento (.warning, user-avatar e .selected-day por exemplo)
Depois de ler isso você deve estar se perguntando, se @extend é tão legal, porque não é tão popular quanto @mixin?
Isso porque @extend pode ser perigoso.
O problema com essa diretiva de estender classe ou id, é que as regras que você estiver estendendo são exibidas encaixadas sobre a aplicação, o SASS deve gerar todas as combinações possíveis entre as classes e as regras que as incluem.
Exemplo:
.button {
display: block;
padding: 10px;
background: green;
}
.sidebar .signup .button {
margin-top: 22px;
}
.registration, .remember-password {
.button {
margin-bottom: 33px;
}
}
.edit-account .delete-area .button{
background-color: red;
color: white;
}
.article a {
@extend .button;
}
Código gerado:
.button, .article a { /* This is probably what you intended to do */
display: block;
padding: 10px;
background: green;
}
/* But it also generates this combinational mess */
.sidebar .signup .button, .sidebar .signup .article a, .article .sidebar .signup a {
margin-top: 22px;
}
.registration .button, .registration .article a, .article .registration a, .remember-password .button, .remember-password .article a, .article .remember-password a {
margin-bottom: 33px;
}
.edit-account .delete-area .button, .edit-account .delete-area .article a, .article .edit-account .delete-area a {
background-color: red;
color: white;
}
.button é uma classe que muito provevelmente será personalizada de acordo com o contexto, por isso com apenas 3 aparições pode ser um desastre, com 10 aparições apenas deixe tente imaginar a merda que vai dar.
Portanto, a regra de ouro é: “Só usar @extend em um seletor se você tem certeza absoluta que não será usado em muitos lugares”.
Mas a parte importante é que você não pode ter sempre certeza disso, e mesmo se você tiver certeza que neste momento você satisfazer essa regra, no futuro, você ou um de seus colegas de trabalho podem, inadvertidamente, estragar tudo.
%placeholders
Os placeholders é uma funcionalidade excelente acrescentada no sass 3.2, e ele veio para consertar a bagunça que eu descrevi antes.
Ao contrário de seletores normais, como .classes ou #IDs, os placeholders nunca serão compilados. Em outras palavrasm este é um pequeno espaço de SASS.
%button{
display: block;
padding: 10px;
background: green;
}
a{ color: blue; }
Vai gerar
a{ color: blue; }
Não há nenhuma referência para o %button, porque os placeholders são espaços reservados nomeados com conjunto de estilos que destinam a ser prorrogado em outros seletores, e não tem existência por si próprio.
Uma ves que eles não tem existência por si só, não podem ser aninhadas, assim você pode usar @extend %placeholder-name com total segurança.
.button, %button {
display: block;
padding: 10px;
background: green;
}
.sidebar .signup .button {
margin-top: 22px;
}
.registration, .remember-password {
.button {
margin-bottom: 33px;
}
}
.edit-account .delete-area .button{
background-color: red;
color: white;
}
.article a {
@extend %button;
}
e você só tem as regras que pretende obter:
.button, .article a {
display: block;
padding: 10px;
background: green;
}
.sidebar .signup .button {
margin-top: 22px;
}
.registration .button, .remember-password .button {
margin-bottom: 33px;
}
.edit-account .delete-area .button {
background-color: red;
color: white;
}
Resumindo
• NUNCA declaer mixins que não aceitam parametros: Isso não são mixins, são classes/placeholders
• NUNCA (ou quase nunca) use extend em seletores normais. Você pode obter resultados inesperados se o seletor aparecer aninhado em outro lugar ou outra folha de estilo. Use placeholders no lugar.
• Não crie seletores “super aninhados”. Com sass é fácil esquecer a cadeia e criar seletores infames com 6-7 regras encadeadas.
• Não usar nomde de tag como seletores se você pode evita-lo. Isso não é uma regra taxativa, mas usar tags como seletores é menos eficiênte que classes ou IDs.
• Não use seletor de herança (“>”). É muito ineficiênte.
• Não use seletor irmão (“+”). É muito ineficiênte e está intimamente ligado à sua marcação atual. Em algumas bibliotecas JavaScript, como Ember.js por exemplo, podem ser inseridos elementos invisíveis e que quebram esse tipo de regra.
• Não confie cegamente no que você acha que o sass está gerando. Verifique a css gerada ao longo do tempo. Você pode descobrir os erros que passam despercebidos no sass.
• Crie uma palheta de cores usando variáveis desde o início. Se você não fizer isso, você pode facilmente acabar facilmente com 50 tons de cinza diferentes que são usados em apenas um ou dois lugares.
• Refatore. Enquanto a maioria das pessoas se preocupa com o código back-end / front-end, o percentual de pessoas que só abrem o estilo existente e acresceta novas regras para um novo widget que ele criou, sem tentar reutilizar os existentes é muito maior.