CSS

27 jul, 2015

Usando o currentColor do CSS

Publicidade

Variáveis no CSS? Em um futuro não muito distante (ou talvez sim) poderemos usar nossas variáveis muito doidas diretamente no CSS, mas enquanto o sol não raia pra nós, conseguimos simular esse recurso através de pré-processadores. Pra mim, o uso de variáveis são umas das principais (e acho que uma das poucas) features que uso dos pré-processadores, mas isso foge um pouco do assunto do artigo (boa ideia para um próximo!).

Variáveis são legais

Se você está acostumado a utilizar um Sass ou LESS da vida, sabe o quão legal e útil pode ser utilizar variáveis quando falamos de estilo. Uma coisa útil é que variáveis nos ajudam a evitar repetições e nos auxiliam (e muito!), principalmente em projetos grandes onde a possibilidade, de por exemplo, ter uma repetição de uma cor específica é bem grande.

Um bom caso de aplicação de variáveis é na questão de temas ou variações de um componente ou até de um projeto inteiro. Criar e gerenciar esquemas de cores com variáveis fica bem mais fácil: podemos criar por exemplo, uma variável chamada main-color e declarar a cor red pra ela. Assim, se em uma manutenção futura, precisarmos mudar essa cor, alteramos apenas na declaração da variável e não em todos os casos onde ela é utilizada. Claro que tudo depende de como estruturamos a coisa toda, pois uma pequena alteração de cor pode te dar alguns problemas.

O tal do currentColor

O danado do currentColor funciona semelhante a uma variável salvo duas exceções: só podemos utilizá-lo onde um valor de cor é esperado e, diferente de uma variável comum, não podemos setar o seu valor, e sim, isso é herdado do valor atual da propriedade color que está sendo usada no elemento e claro, seguindo a cascata. Ficou confuso? Eu também. Vamos lá!

Vamos supor que tenhamos o seguinte:

body { color: green; }

div {
  color: currentColor;
  box-shadow: 1px 1px 1px 1px currentColor;
  outline: dotted 1px currentColor;
}

No exemplo acima, simplesmente definimos uma cor verde para o body e a utilizamos nos elementos div através dos caras currentColor. Mas Fabeni, tu tá me enrolando! Eu não precisava do currentColor aí! Exatamente, não precisava. Se voltarmos para o exemplo, chegaríamos no mesmo resultado apenas assim:

body { color: green; }

div {
  box-shadow: 1px 1px 1px 1px;
  outline: dotted 1px;
}

Algumas propriedades herdam o valor da propriedade color do elemento, ou caso essa não tenha sido setada, segue a cascata, até achar da onde vão herdar esse valor. Algumas dessas propriedades são:

  • O elemento texto em si;
  • A borda do elemento;
  • outline;
  • Box-shadow;
  • Bullets de uma lista.

No exemplo abaixo, é possível ver que alterando a cor do body, todos os elementos que herdam essa cor, sofrem modificação de estilo.

HTML

<form id="form">
  <label for="blue">
    <input type="radio" name="color" id="blue" checked/> blue
  </label>
  <label for="red">
    <input type="radio" name="color" id="red" /> red
  </label>
  <label for="green">
    <input type="radio" name="color" id="green" /> green
  </label>
</form>
<div>
  <p>text (color)</p>
  <p class="outline">text (outline)</p>
  <ul>
    <li>Item list (border and color)</li>
  </ul>
  <span><span>bg color (with currentColor)</span></span>
</div>

CSS

body {
  font-family: Tahoma;
  font-size: 18px;
  padding: 20px;
}

body,
body.blue { color: #3498db; }
body.green { color: #27ae60; }
body.red { color: #e74c3c; }

form {
  margin: 0 0 15px 0;
}

div {
  border: solid 5px;
  box-shadow: 1px 1px 10px 2px;
  padding: 20px;
  max-width: 300px;
}

div > span {
  background-color: currentColor;
  display: block;
  padding: 10px;
}

div > span > span { color: #fff; }

p { margin: 15px 0; }

.outline { outline: dotted 1px; }

ul li {
  border: solid 1px;
  padding: 2px;
}

JavaScript

(function() {
  var colors = document.getElementById('form').color,
      hold = document.getElementsByTagName("body")[0];
  
  for(var i = 0; i < colors.length; i++) {
    colors[i].addEventListener('click', changeColor, false);
  }
  
  function changeColor() {
    hold.classList.remove(hold.classList[0]);
    hold.classList.add(this.id);
  }
}());

Resultado:

imagem 7

Mas, então, você deve estar se perguntando: qual a real utilidade disso? Agora que as coisas começam a ficar legais e, dependendo da sua criatividade e organização, dá pra fazer algumas coisas bem bacanas.

É possível usar, por exemplo, em animações, svg, gradientes… E por aí vai. Fuçando pela interwebs da vida, achei esse exemplo que, através de uma animação, altera a cor do elemento body, mudando assim o currentColor usado em outro elemento.

Brincando um pouco, montei esse exemplo rápido, onde o currentColor é aplicado no :after do elemento.

HTML

<a href="#" class="btn">Hello</a>
<a href="#" class="btn btn-blue">Hello</a>
<a href="#" class="btn btn-green">Hello</a>
<a href="#" class="btn btn-red">Hello</a>

CSS

body { padding: 10px; }

.btn {
  color: #888;
  text-decoration: none;
  font-family: Helvetica;
  font-size: 16px;
  transition: color .3s ease;
  border: solid 1px;
  padding: 10px 15px;
  margin: 5px;
  border-radius: 5px;
}

.btn:hover { color: #000; }

.btn-blue { color: #3498DB; }
.btn-blue:hover,
.btn-blue:focus{ color: #446CB3; }

.btn-red { color: #F64747; }
.btn-red:hover,
.btn-red:focus{ color: #C0392B; }

.btn-green { color: #68C3A3; }
.btn-green:hover,
.btn-green:focus{ color: #019875; }

.btn:after {
  width: 0;
  height: 0;
  border: 0.4em solid transparent;
  border-left-color: currentColor;
  content: '';
  display: inline-block;
  position: relative;
  top: 1px;
  left: 5px;
  transition: transform ease .3s;
}

.btn:hover:after { transform: translateX(3px); }

A ideia para formar o triângulo é criar uma borda geral transparente e setar apenas o lado que você quer com ocurrentColor, formando assim o triângulo. Uma outra abordagem e, que chegaria no mesmo resultado, seria fazer o processo inverso: setar uma borda geral com cor (no caso nem precisaria do currentColor, pois ele herdaria a cor da propriedade color) e, depois disso, tirar a borda dos lados que você não queira. Algo mais ou menos assim:

.element:after {
    border: 0.4em solid;
    border-right-color: transparent;
    border-top-color: transparent;
    border-bottom-color: transparent;
}

Outros usos

É possível usar nosso camarada em SVGs. Fiz um exemplo rápido (abaixo) onde o SVG herda a cor da propriedade color do elemento pai (a classe .alert):

HTML

<div class="alert">
  <svg height="50px" version="1.1" viewBox="0 0 512 512" width="50px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M256.1,96L256.1,96c-79.9,0-155.7,29.9-213.9,84.1L32,189.6l9.9,9.8l32.3,32l9.3,9.2l9.6-8.8   c44.5-40.9,102.3-63.5,162.8-63.5c60.5,0,118.4,22.6,162.8,63.5l9.6,8.8l9.3-9.2l32.3-32l9.9-9.8l-10.2-9.5   C411.6,125.9,335.7,96,256.1,96z"/><path d="M397.4,256.4c-38.8-35.1-88.9-54.4-141.1-54.4h-0.1h-0.3h-8.5l-0.1,0.2c-49.2,2-96,21.1-132.6,54.2l-10.5,9.5l10.1,10   l32.7,32.4l9.1,9l9.6-8.4c25.3-22.2,57.4-34.5,90.3-34.5c33.1,0,65.2,12.3,90.5,34.5l9.6,8.4l9.1-9l32.7-32.4l10.1-10L397.4,256.4z   "/><path d="M256.2,416l9.6-9.5l52.8-52.2l10.6-10.5l-11.6-9.5c-15.4-11.4-32.4-20-61.5-20c-29,0-44.9,9.4-61.5,20l-11.5,9.5l10.6,10.5   l52.8,52.2L256.2,416z"/></g></svg>
  We do not have wifi!
</div>

<div class="alert alert-red">
  <svg height="50px" version="1.1" viewBox="0 0 512 512" width="50px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M256.1,96L256.1,96c-79.9,0-155.7,29.9-213.9,84.1L32,189.6l9.9,9.8l32.3,32l9.3,9.2l9.6-8.8   c44.5-40.9,102.3-63.5,162.8-63.5c60.5,0,118.4,22.6,162.8,63.5l9.6,8.8l9.3-9.2l32.3-32l9.9-9.8l-10.2-9.5   C411.6,125.9,335.7,96,256.1,96z"/><path d="M397.4,256.4c-38.8-35.1-88.9-54.4-141.1-54.4h-0.1h-0.3h-8.5l-0.1,0.2c-49.2,2-96,21.1-132.6,54.2l-10.5,9.5l10.1,10   l32.7,32.4l9.1,9l9.6-8.4c25.3-22.2,57.4-34.5,90.3-34.5c33.1,0,65.2,12.3,90.5,34.5l9.6,8.4l9.1-9l32.7-32.4l10.1-10L397.4,256.4z   "/><path d="M256.2,416l9.6-9.5l52.8-52.2l10.6-10.5l-11.6-9.5c-15.4-11.4-32.4-20-61.5-20c-29,0-44.9,9.4-61.5,20l-11.5,9.5l10.6,10.5   l52.8,52.2L256.2,416z"/></g></svg>
  We do not have wifi!
</div>

<div class="alert alert-green">
  <svg height="50px" version="1.1" viewBox="0 0 512 512" width="50px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M256.1,96L256.1,96c-79.9,0-155.7,29.9-213.9,84.1L32,189.6l9.9,9.8l32.3,32l9.3,9.2l9.6-8.8   c44.5-40.9,102.3-63.5,162.8-63.5c60.5,0,118.4,22.6,162.8,63.5l9.6,8.8l9.3-9.2l32.3-32l9.9-9.8l-10.2-9.5   C411.6,125.9,335.7,96,256.1,96z"/><path d="M397.4,256.4c-38.8-35.1-88.9-54.4-141.1-54.4h-0.1h-0.3h-8.5l-0.1,0.2c-49.2,2-96,21.1-132.6,54.2l-10.5,9.5l10.1,10   l32.7,32.4l9.1,9l9.6-8.4c25.3-22.2,57.4-34.5,90.3-34.5c33.1,0,65.2,12.3,90.5,34.5l9.6,8.4l9.1-9l32.7-32.4l10.1-10L397.4,256.4z   "/><path d="M256.2,416l9.6-9.5l52.8-52.2l10.6-10.5l-11.6-9.5c-15.4-11.4-32.4-20-61.5-20c-29,0-44.9,9.4-61.5,20l-11.5,9.5l10.6,10.5   l52.8,52.2L256.2,416z"/></g></svg>
  We do not have wifi!
</div>

CSS

body { font-family: Arial; }

.alert {
  position: relative;
  color: gray;
  border: solid 2px;
  border-radius: 10px;
  font-size: 30px;
  letter-spacing: -1px;
  padding: 15px 15px 15px 115px;
  max-width: 300px;
  margin: 15px;
}

.alert:after,
.alert:before {
  content: "";
  position: absolute;
  top: 50%;
  margin-top: -6px;
  width: 12px;
  height: 12px;
  background-image: linear-gradient(
    to bottom, 
    currentColor 0%,
    currentColor 48%,
    #fff 49%,
    #fff 55%,
    currentColor 56%);
  border-radius: 50%;
  box-shadow: inset 0 0 8px 0 rgba(0,0,0,.5);
}

.alert:after {
  right: 15px;
  transform: rotate(45deg);
}

.alert:before {
  left: 15px;
  transform: rotate(-45deg);
}

.alert svg {
  position: absolute;
  left: 50px;
  top: 5px;
  fill: currentColor;
}

.alert-red { color: #e74c3c; }
.alert-green { color: #27ae60; }

Resultados

imagem 8

Só isso?! Basicamente sim e não. Aqui que entra a nossa criativade e organização em tirar proveito do que ocurrentColor nos oferece.

Mas e aí, dá pra usar?

O suporte é bem melhor do que eu imaginava. IE9, Chrome, Firefox, Safari e por aí vai… Existe um pequeno bug bem pontual, para Safari e iOS Safari 8, quando aplicado em :after e :before. Dá pra ver mais informações no site do Can I Use.

Gostou? Escrevi alguma groselha? Quer melhorar? Abra uma issue mencionando o post e vamos conversar.

***

Artigo publicado originalmente em: http://www.raphaelfabeni.com.br/current-color-css/