Entendendo Escopo de Variáveis no Sass
() translation by (you can also view the original English article)
Nesse artigo, aprofundaremo-nos nas variáveis e escopos de variáveis do Sass. O escopo de uma variável descreve o contexto em que ela é definida e, assim, onde ela está disponível.
Para começar, cobriremos que escopos Sass suporta. Depois, explicaremos dois semáforos úteis que podemos usar para customizar o valor de uma variável. Por fim, apresentaremos as funções disponívels para verificar se uma variável existe ou não.
Escopo de Variável do Sass
Sass suporte dois tipos de variáveis: locais e globais.
Por padrão, todas variáveis definidas foras de qualquer seletor, são consideradas globais. Isso significa que elas podem ser acessíveis em qualquer lugar da folha de estilo. Por exemplo, eis uma variável global:
1 |
$bg-color: green; |
Por outro lado, variáveis locais são aquelas declaradas dentro de um seletor. Depois, veremos como customizar esse comportamento. Por hora, vejamos nosso primeiro exemplo.
Aqui, definimos uma mixin e então a variável btn-bg-color
dentro. Essa variável é local e, assim, visível apenas para o código dentro da mixin.
1 |
@mixin button-style { |
2 |
$btn-bg-color: lightblue; |
3 |
color: $btn-bg-color; |
4 |
}
|
Agora, podemos invocar a mixin, dessa forma:
1 |
button { |
2 |
@include button-style; |
3 |
}
|
O CSS resultante:
1 |
button { |
2 |
color: lightblue; |
3 |
}
|
Imaginemos, porém, que também queremos usar essa variável (não a mixin) em outro seletor:
1 |
.wrap { |
2 |
background: $btn-bg-color; |
3 |
}
|
Isso nos daria o erro a seguir:
1 |
Undefined variable: "$btn-bg-color". |
Isso era esperado, certo? Tentamos acessar a variável da mixin, de um escopo local. Não nos preocupemos. Como mencionado, ajustaremos esse problema em uma seção posterior.
Seletores Aninhados
Vale a pena mencionar que, se declaramos uma variável dentro de um seletor, qualquer seletor aninhado tem acesso a ela. Eis um exemplo:
1 |
.wrap { |
2 |
$bg-color: red; |
3 |
|
4 |
&:after { |
5 |
background: lighten($bg-color, 10%); |
6 |
}
|
7 |
}
|
8 |
Compila em:
1 |
.wrap:after { |
2 |
background: #ff3333; |
3 |
}
|
Contudo, vejamos o exemplo abaixo, onde definimos uma função e, então, usamo-na em um seletor aninhado:
1 |
@function my-function() { |
2 |
$text-color: black; |
3 |
@return $text-color; |
4 |
}
|
5 |
|
6 |
.wrap { |
7 |
color: my-function(); |
8 |
|
9 |
&:after{
|
10 |
background: $text-color; |
11 |
}
|
12 |
}
|
Se tentarmos compilar isso, obteremos o mesmo erro discutido antes. De novo, isso acontece porque não podemos acessar a variável text-color
. Não está definida diretamente dentro do seletor pai, mas dentro da função que o seletor invoca.
Nomes de Variáveis
Variáveis globais e locais podem ter nomes iguais. Para mostrar o comportamento, veremos um quarto exemplo:
1 |
$text-color: tomato; |
2 |
|
3 |
@mixin button-style { |
4 |
$text-color: lime; |
5 |
color: $text-color; |
6 |
}
|
7 |
|
8 |
@mixin link-style { |
9 |
$text-color: black; |
10 |
color: $text-color; |
11 |
}
|
Aqui, definimos três variáveis diferentes (text-color
) com o mesmo nome. A primeira é global, enquanto as outras duas são locais.
Eis alguns estilos que lançam mão delas:
1 |
button { |
2 |
@include button-style; |
3 |
}
|
4 |
|
5 |
a { |
6 |
@include link-style; |
7 |
}
|
8 |
|
9 |
.wrap { |
10 |
background: $text-color; |
11 |
}
|
E o CSS gerado:
1 |
button { |
2 |
color: lime; |
3 |
}
|
4 |
|
5 |
a { |
6 |
color: black; |
7 |
}
|
8 |
|
9 |
.wrap { |
10 |
background: tomato; |
11 |
}
|
Isso é o que era esperado?
Tenhamos em mente que não veremos esses estilos a não ser que compilemos com a versão mais atual de Sass (3.4). Por exemplo, suponhamos que usamos Sass 3.3, nosso retorno seria:
1 |
button { |
2 |
color: lime; |
3 |
}
|
4 |
|
5 |
a { |
6 |
color: black; |
7 |
}
|
8 |
|
9 |
.wrap { |
10 |
background: black; |
11 |
}
|
Potemos a diferença da cor do background em .wrap
. Isso se dá porque, em versões anteriores do Sass (no LibSass também), se redefinirmos localmente o valor de uma global (text-color
, por exemplo), esse será o novo valor da variável global. Assim, em nosso exemplo, o estilo compilado depende da ordem que declaramos a variável e as mixins.
O Semáforo default
Esse semáforo permite-nos configurar o valor de uma variável no caso dela não ter sido configurada ou for null
(não atribibuída). Para explicar melhor, lançaremos mão de um cenário real. Suponhamos que temos um projeto com a estrutura a seguir:
1 |
Project-Name/ |
2 |
├── ... |
3 |
├── css/ |
4 |
│ └── app.css |
5 |
└── scss/ |
6 |
├── _config.scss |
7 |
├── _variables.scss |
8 |
├── _mixins.scss |
9 |
└── app.scss |
O arquivo app.scss
parece com isso:
1 |
@import "config"; |
2 |
@import "variables"; |
3 |
@import "mixins"; |
4 |
|
5 |
button { |
6 |
@include button-style; |
7 |
}
|
8 |
|
9 |
// more styles |
Vejamos o conteúdo dos arquivos parciais.
Primeiro, o arquivo variables.scss
contém nossas variáveis:
1 |
$btn-bg-color: lightblue !default; |
2 |
$btn-bg-color-hover: darken($btn-bg-color, 5%); |
3 |
|
4 |
// more variables |
Notemos o semáforo default
atribuído a btn-bg-color
.
Segundo, o arquivo mixins.scss
inclui nossas mixins:
1 |
@mixin button-style ($bg-color: $btn-bg-color, $bg-color-hover: $btn-bg-color-hover) { |
2 |
background-color: $bg-color; |
3 |
// more styles |
4 |
|
5 |
&:hover { |
6 |
background-color: $bg-color-hover; |
7 |
// more styles |
8 |
}
|
9 |
}
|
10 |
|
11 |
// more mixins |
Então, o arquivo app.css
gerá será assim:
1 |
button { |
2 |
color: lightblue; |
3 |
}
|
4 |
|
5 |
button:hover { |
6 |
background-color: #99cfe0; |
7 |
}
|
Assim, nossos botões vem com estilos padrão. Mas, suponhamos que queremos a opção de sobrescrevê-las, aplicando nossos valores customizados. Para tanto, podemos reatribuir as variáveis desejadas (padrão) no arquivo parcial config.scss
.
1 |
$btn-bg-color: chocolate; |
2 |
|
3 |
// more variables |
Configurando o valor da variável para chocolate
resultará no nõ uso do valor correspondente (lightblue
) que recebeu o semáforo default
. Assim, o CSS gerado mudará para o seguinte:
1 |
button { |
2 |
color: chocolate; |
3 |
}
|
4 |
|
5 |
button:hover { |
6 |
background-color: #bc5e1b; |
7 |
}
|
Nota: se não tivéssemos adicionado o semáforo default
à variável btn-bg-color
, nosso CSS seria o seguinte, pode conta da cascata do CSS:
1 |
button { |
2 |
color: lightblue; |
3 |
}
|
4 |
|
5 |
// hover styles |
O Semáforo global
Esse ajuda na mudança de escopo de variáveis locais.
Lembremo-nos do erro que vimos no primeiro exemplo. Pois bem, aquilo aconteceu porque tentamos usar a variável btn-bg-color
no seletor .wrap
. Modifiquemos o exemplo pra incluir esse semáforo. Eis o novo estilo:
1 |
@mixin button-style { |
2 |
$btn-bg-color: lightblue !global; |
3 |
color: $btn-bg-color; |
4 |
}
|
5 |
|
6 |
button { |
7 |
@include button-style; |
8 |
}
|
9 |
|
10 |
.wrap { |
11 |
background: $btn-bg-color; |
12 |
}
|
Como vemos abaixo, graças ao semáforo, o CSS compila sem problemas:
1 |
button { |
2 |
color: lightblue; |
3 |
}
|
4 |
|
5 |
.wrap { |
6 |
background: lightblue; |
7 |
}
|
O semáforo global
é útil, mas lembre-se que não é sempre uma boa prática mudar o escopo de uma variável.
Verificando Se Uma Variável Existe
Sass provê duas funções introspectivas para testar se uma variável existe ou não. Podemos usar as funções variable-exists
e/ou global-variable-exists
para verificar se variáveis locais e/ou globais existem, respectivamente.
Por exemplo, eis um caso de uso, onde definimos uma variável contendo o caminho absoluto de uma Fonte do Google. Então, escolhemos importar a fonte em nossas folhas de estilos mas, apenas, se a variável relevante for instanciada.
1 |
$google-font: "http://fonts.googleapis.com/css?family=Alegreya"; |
2 |
|
3 |
@if(global-variable-exists(google-font)) { |
4 |
@import url($google-font); |
5 |
}
|
O resultado:
1 |
@import url("http://fonts.googleapis.com/css?family=Alegreya"); |
Conclusão
Nesse artigo, introduzimos o conceito de escopo de variáveis no Sass. Para clarear as coisas, vimos exemplos diferentes, então esperamos que tenham um melhor entendimento do funcionamento do escopo. Pode-se encontrar todos os exemplos do artigo nesse gist do SassMeister. Sinta-se a vontade para perguntar o que precisar nos comentários!