A Cascata das Variáveis do CSS

Suporte | Especificação

Muito embora todos os seres humanos do Planeta Terra tenham odiado sua sintaxe, as variáveis finalmente chegaram ao CSS – e elas são mais poderosas do que você imagina!


Esse artigo faz parte da série O CSS do Futuro.

Motivação

O desenvolvimento de grandes aplicações web implica inevitavelmente em grandes folhas de estilo, que devem ser organizadas de forma que facilite a manutenção. Muitos valores definidos para propriedades são repetidos, quando poderiam ser reutilizados e padronizados, de forma compartilhada, pela folha de estilo.

Nesse contexto, surgem as variáveis no CSS, também chamadas de Custom Properties – pois, tecnicamente, é isso que elas são.

Definição

As Custom Properties são propriedades CSS customizadas (ou seja, você configura o seu valor) iniciadas com --, de nome case-sensitive, e que são utilizadas no documento através da função var(). Por serem propriedades, é importante compreender que seu comportamento é idêntico ao de uma propriedade qualquer do CSS (guarde essa informação!).

Exemplo

:root {
  --colorPrimary: purple;
}

a {
  color: var(--colorPrimary);
}

(Eu não conheço ninguém que gosta da ideia esplêndida do --. Mas elas não vão deixar de iniciar com -- se você reclamar. Inclusive, isso já foi discutido o suficiente.)

A função var()

Quem viabiliza o uso de Custom Properties? Ela:

var( <custom-property-name> [, <declaration-value> ]? )

O primeiro parâmetro é o nome da propriedade, e o segundo, opcional, é o valor a ser usado como fallback caso o primeiro argumento seja inválido (por exemplo: uma variável com 20px sendo usada como valor de um background, ou variável inexistente).

Escopo

Cascata, especificidade, herança… Esses conceitos são muito importantes para entender o poder das variáveis do CSS – e do CSS no geral, eu diria.

Aqui, uma das informações mais importantes deste artigo:

As Custom Properties seguem regras de cascata tal como qualquer outra propriedade do CSS.

Por isso, quando quisermos que a variável esteja disponível “globalmente” (para todos os seletores), a declaramos no seletor :root, que é o próprio documento HTML. Isso acontece pois o efeito cascata do CSS permite que todos seus descendentes herdem a propriedade. Legal, né?

A propriedade customizada, tal como qualquer outra propriedade, pode ser sobreescrita através de seletores. Seu valor será definido de acordo com a especifidade deles.

A implementação de Custom Properties do CSSNext não segue regras de cascata. Apenas variáveis declaradas no :root são válidas. 😦

Exemplo

:root {
  --bgColor: indianred;
}

div {
  --bgColor: darkseagreen;
}

#wow {
  --bgColor: darkcyan;
}

* {
  background-color: var(--bgColor);
}

Nesse caso:

  • Todos os elementos são vermelhos.
  • Exceto elementos div e seus filhos, que seriam verdes.
  • Exceto o elemento com id wow e seus filhos, que seriam ciano.

As últimas versões do Firefox e Chrome já implementaram as variáveis nativas do CSS. Se estiver utilizando algum desses navegadores, o exemplo abaixo ilustrará o funcionamento do CSS acima.

JS Bin on jsbin.com

Manipulando variáveis CSS com JavaScript

Outra informação valiosa sobre as variáveis do CSS é a possibilidade de acessá-las e alterá-las via JavaScript, usando a interface CSSStyleDeclaration para interagir com propriedades.

Exemplo

Considerando:

:root {
  --my-color: darkcyan;
  background-color: var(--my-color);
}

Você pode obter o valor da propriedade --my-color, através do window.getComputedStyle() e getPropertyValue().

const myColor = getComputedStyle(document.body).getPropertyValue('--my-color')
console.log(myColor) // => darkcyan

Você pode alterar o valor da variável, através do setProperty() do objeto style:

document.body.style.setProperty('--my-color', 'tomato')

Conheça o CSSStyleDeclaration abrindo o DevTools e digitando getComputedStyle(document.body) no console.

Curiosidades

  • Você não pode armazenar nomes de propriedades do CSS como Custom Properties.
div {
  --myProperty: overflow;
  var(--myProperty): hidden; /* Erro de sintaxe */
}

…Em compensação, você pode armazenar qualquer outra coisa (e usá-las com JavaScript!):

--foo: if (x > 5) this.width = 10;
  • Você não pode formar valores com variáveis.
div {
  --myContainerWidth: 300;
  width: var(--myContainerWidth)px; /* Valor inválido */
  /* => 300 px, em vez de 300px */
}

…Ao menos que você use calc():

    div {
    --myContainerWidth: 300;
    width: calc(var(--myContainerWidth) * 1px); /* => width: 300px; */
  }

Considerações Finais

As Custom Properties abriram novas possibilidades para o uso de variáveis em folhas de estilo. Depois de diversas especificações e sintaxes (nem sempre foi --, acredite!), elas estão finalmente em fase de implementação nos navegadores.

Tem interesse em se aprofundar em outras novas funcionalidades do CSS? Acompanhe a série O CSS do Futuro!