Texto com degradê em CSS (igual a esse título)

Publicado em 16 set 2020. Uns 4 minutos de leitura.

A cor do texto em CSS é definida usando a propriedade color. Mas há maneiras de usar algo mais complexo do que apenas uma cor? Dá sim, é só olhar para o título deste post. O texto nele, ao invés de ter uma cor apenas, é preenchido por um degradê (ou gradiente). Vamos fazer isso só com CSS!

/* Exemplo apenas com `color` */
.single-color {
  color: steelblue;
}

/* Agora, colocando um degradê */
.gradient {
  /* Primeiro passo: definir um degradê como fundo */
  background-image: linear-gradient(to bottom, rebeccapurple, steelblue, turquoise);
  
  /* Segundo passo: apagar do fundo tudo que não estiver imediatamente atrás de texto */
  background-clip: text;
  -webkit-background-clip: text; /* Alguns navegadores precisam do prefixo */

  /* Terceiro passo: apagar o texto, deixando apenas o fundo atrás dele */
  -webkit-text-fill-color: transparent;

  /* Cor que contraste com o degradê, caso o navegador não suporte `background-clip: text` */
  color: black;
  
}

/* Não relacionado ao degradê, apenas para melhorar a visualização */
p {
  font-size: 3rem;
  font-weight: bold;
  line-height: 1.1;
}
<p class="single-color">Eu tenho só uma cor.</p>
<p class="gradient">Eu sou colorido! 🤟</p>

Eu tenho só uma cor.

Eu sou colorido! 🤟

Se ignorarmos os comentários, com 3 linhas a mais temos um texto com degradê! Eu coloquei acima o que cada linha do CSS faz, mas vamos dar uma rápida passada pelo que está acontecendo aqui. Vamos montar cada etapa do exemplo acima.

Adicionar um degradê

Primeiro, precisamos ter um degradê. Em CSS, degradês são suportados como imagens de fundo. Usando background-image, podemos criar um degradês lineares, radiais e cônicos. No exemplo acima, usei um linear-gradient no sentido de cima para baixo (to bottom).

.gradient {
  background-image: linear-gradient(to bottom, rebeccapurple, steelblue, turquoise);
  color: black;
}

p {
  font-size: 3rem;
  font-weight: bold;
  line-height: 1.1;
}
<p class="gradient">Eu sou colorido! 🤟</p>

Eu sou colorido! 🤟

Adicionalmente, eu coloquei um color no texto que constraste com o degradê. Essa cor não vai ser utilizada no nosso efeito, e está lá apenas para contrastar com o degradê em navegadores antigos que não permitam transformar o fundo em texto, como vamos fazer agora.

Transformar o fundo em texto

Vamos agora usar a propriedade background-clip. Ela serve para limitar a visualização do plano de fundo do elemento. Vamos usar o valor text, que significa "apenas exiba o background que esteja embaixo de algum texto.

.gradient {
  background-image: linear-gradient(to bottom, rebeccapurple, steelblue, turquoise);
  color: black;

  /* Adicionado: */
  background-clip: text;
  -webkit-background-clip: text;
}

p {
  font-size: 3rem;
  font-weight: bold;
  line-height: 1.1;
}
<p class="gradient">Eu sou colorido! 🤟</p>

Eu sou colorido! 🤟

… … … ué. O degradê sumiu? Mais ou menos. Ele ainda está lá, mas não podemos vê-lo pois o background-clip: text não esconde o próprio texto. Ou seja, o background está limitado apenas a área que estava embaixo de um texto, e o próprio texto está aparecendo por cima dele, na cor preta (color: black). Precisamos de um toque final para chegar no nosso efeito desejado.

Escondendo o texto

O WebKit definiu uma propriedade que serve para sobrescrever a color do texto, que é a -webkit-text-fill-color. Se ela estiver definida, ela tem preferência em relação à color. Vamos usá-la para deixar o texto transparente (transparent) e, assim conseguirmos ver o background que está atrás dele. Apesar do prefixo -webkit, ela é suportada por todos os navegadores modernos.

.gradient {
  background-image: linear-gradient(to bottom, rebeccapurple, steelblue, turquoise);
  color: black;
  background-clip: text;
  -webkit-background-clip: text;

  /* Adicionado: */
  -webkit-text-fill-color: transparent;
}

p {
  font-size: 3rem;
  font-weight: bold;
  line-height: 1.1;
}
<p class="gradient">Eu sou colorido! 🤟</p>

Eu sou colorido! 🤟

Alternativamente, poderíamos definir a cor do texto diretamente com color: transparent. Porém, usuários em navegadores bem antigos, em que o background-clip: text não funciona, não iriam ver o texto. Estes navegadores não vão ter suporte ao -webkit-text-fill-color, então a color vai aparecer. Note também que, agora que estamos vendo o plano de fundo e não o texto de fato, até Emoji vai aparecer nas cores do fundo.

Vale dizer que essas propriedades não servem apenas para degradês, mas para qualquer plano de fundo do elemento, como imagens. O processo é o mesmo: definir o plano de fundo, limitar o plano de fundo ao texto e esconder o texto. O suporte é razoavelmente bom, incluindo em dispositivos móveis. E, para os que não suportam, há o fallback que deixa o texto ainda visível.