CSS e web

Gradientes SVG: lineares, radiais, contornos, texto e máscaras

O SVG tem o seu próprio sistema de gradientes, mais antigo do que os gradientes CSS e capaz de coisas que eles não conseguem: colorir um contorno, preencher uma palavra, partilhar um gradiente por várias formas e esbater qualquer coisa com uma máscara.

GradientlyConta Gradiently verificada··6 min de leitura
Capa: Cold Salon · GR·4AB2·SW

A versão curta

  • Um gradiente SVG define-se uma vez como um elemento linearGradient ou radialGradient com filhos stop, recebe um id e aplica-se com fill ou stroke definidos como url(#id).
  • Por omissão, as coordenadas dos gradientes SVG usam unidades objectBoundingBox, em que 0 e 1 são as margens da forma que está a ser pintada.
  • gradientUnits="userSpaceOnUse" coloca o gradiente nas coordenadas do próprio desenho, o que permite que um gradiente abranja várias formas e corrige os gradientes em linhas perfeitamente retas.
  • spreadMethod decide o que acontece para lá das pontas do gradiente: pad mantém as cores das pontas, reflect espelha a mistura e repeat recomeça-a.
  • Uma máscara SVG usa a luminosidade, por isso um gradiente de branco a preto dentro de uma máscara esbate aquilo a que for aplicado.
Nesta página

Um gradiente SVG é uma tinta que defines uma vez e aplicas a qualquer forma, linha ou texto num SVG. Escreves um elemento <linearGradient> ou <radialGradient> dentro de <defs>, dás-lhe filhos <stop> para as cores e um id, e depois defines o fill ou o stroke de uma forma como url(#id). Ao contrário de um fundo CSS, pode colorir um contorno ou uma única palavra, e acompanha a escala do desenho.

html
<svg viewBox="0 0 200 120" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="dusk" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#1e1b4b" />
      <stop offset="0.55" stop-color="#7c3aed" />
      <stop offset="1" stop-color="#f472b6" />
    </linearGradient>
  </defs>
  <rect width="200" height="120" rx="16" fill="url(#dusk)" />
</svg>
Um gradiente diagonal num retângulo arredondado. x1, y1, x2 e y2 traçam a linha do gradiente do canto superior esquerdo ao inferior direito.
A mesma mistura, em CSSlinear-gradient(135deg, #1e1b4b 0%, #7c3aed 55%, #f472b6 100%)
O SVG acima e este gradiente CSS coincidem num quadrado. Num retângulo, a versão SVG estica-se com a forma; vê gradientUnits mais abaixo.

linearGradient e as suas paragens

x1, y1, x2 e y2 definem o início e o fim da linha do gradiente. Cada <stop> recebe um offset de 0 a 1 (ou de 0% a 100%), um stop-color e um stop-opacity opcional. stop-color também é uma propriedade CSS, por isso podes dar tema aos gradientes a partir de uma folha de estilos, por exemplo stop { stop-color: var(--accent); }.

AtributoPor omissãoO que faz
x1 y1 x2 y20 0 1 0, da esquerda para a direitaPontos de início e de fim da linha do gradiente
gradientUnitsobjectBoundingBoxSe as coordenadas são relativas à forma ou ao desenho
spreadMethodpadO que acontece para lá das pontas: pad, reflect ou repeat
gradientTransformnenhumRoda, escala ou inclina o gradiente, por exemplo rotate(30)
hrefnenhumHerda paragens e definições de outro gradiente
Os principais atributos de linearGradient. radialGradient partilha todos menos a primeira linha.

href poupa repetição. Define as tuas paragens uma vez num gradiente base e depois cria variações que apontam para ele e mudam só a direção ou as unidades. A referência de linearGradient na MDN explica todos os atributos.

radialGradient: centro, raio e ponto focal

Um gradiente radial recebe um centro (cx, cy) e um raio (r), todos com 0.5 por omissão, por isso preenche a forma a partir do meio. Tem também algo que falta ao CSS: um ponto focal separado (fx, fy) onde começa a primeira cor. Deslocar o ponto focal para fora do centro faz uma esfera parecer iluminada de um lado.

html
<radialGradient id="orb" cx="0.5" cy="0.5" r="0.5" fx="0.32" fy="0.28">
  <stop offset="0" stop-color="#e0f2fe" />
  <stop offset="0.45" stop-color="#0ea5e9" />
  <stop offset="1" stop-color="#082f49" />
</radialGradient>

<circle cx="60" cy="60" r="50" fill="url(#orb)" />
Um ponto focal para cima e para a esquerda transforma um círculo liso numa esfera brilhante.
Esfera iluminada, aproximada em CSSradial-gradient(circle at 32% 28%, #e0f2fe, #0ea5e9 35%, #082f49 80%)
O CSS consegue mover o centro, mas não separar centro e foco, por isso isto é só uma aproximação da esfera SVG. Compara com gradientes radiais em CSS.

gradientUnits: objectBoundingBox ou userSpaceOnUse

Com o valor por omissão objectBoundingBox, 0 e 1 significam as margens da forma que estiver a ser pintada, por isso cada forma recebe o gradiente inteiro, esticado para caber. Com userSpaceOnUse, as coordenadas estão nas unidades do próprio SVG, por isso o gradiente fica parado e as formas revelam a parte dele que cobrem. É assim que uma fila de barras pode partilhar um gradiente contínuo.

objectBoundingBox

  • Coordenadas de 0 a 1 ao longo de cada forma
  • Cada forma mostra o gradiente completo
  • O gradiente estica-se com as proporções da forma
  • Falha numa linha perfeitamente horizontal ou vertical

userSpaceOnUse

  • Coordenadas nas unidades do próprio desenho
  • As formas revelam a sua fatia de um só gradiente
  • Os ângulos mantêm-se certos seja qual for a forma
  • Funciona em linhas retas e contornos finos

Gradientes em contornos e em texto

stroke="url(#id)" pinta contornos, e é assim que se desenham ícones com gradiente, anéis de progresso e linhas de gráficos. Em <text>, fill="url(#id)" colore as letras, e as palavras continuam selecionáveis e pesquisáveis. Junta uma cor lisa depois do URL, como fill="url(#dusk) #7c3aed", e ela é usada se o gradiente não for encontrado.

html
<svg viewBox="0 0 320 120" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="line" gradientUnits="userSpaceOnUse" x1="20" y1="0" x2="300" y2="0">
      <stop offset="0" stop-color="#22d3ee" />
      <stop offset="1" stop-color="#a855f7" />
    </linearGradient>
  </defs>
  <path d="M20 90 C 90 20, 160 110, 300 30" fill="none" stroke="url(#line)" stroke-width="6" stroke-linecap="round" />
  <text x="20" y="115" font-size="20" font-weight="700" fill="url(#line) #7c3aed">Growth</text>
</svg>
Um gradiente em unidades do desenho, partilhado por uma curva e uma palavra. Ambas vão do ciano ao roxo ao longo da mesma extensão horizontal.

Para letras com gradiente em HTML e não em SVG, texto com gradiente em CSS é normalmente mais simples. Recorre ao texto SVG quando as palavras fazem parte de uma ilustração ou de um logótipo, ou precisam de seguir um traçado.

spreadMethod: pad, reflect e repeat

Quando a linha do gradiente é mais curta do que a forma, spreadMethod decide o que preenche o resto. pad mantém as cores das pontas, reflect espelha a mistura para trás e para a frente e repeat recomeça-a com uma aresta nítida. Aqui cada gradiente vai de 30% a 70% da largura.

Do azul-petróleo à areia com os três métodos de extensão, reproduzidos em CSS para os comparares lado a lado.

Esbater com máscaras SVG

Uma máscara usa a luminosidade: as áreas brancas mostram o que está mascarado, as pretas escondem-no e os cinzentos ficam no meio. Assim, um gradiente de branco a preto dentro de uma <mask> esbate suavemente qualquer forma ou imagem até ao nada, e é assim que se suaviza a margem de uma foto ou se faz uma linha de gráfico desaparecer no início.

html
<defs>
  <linearGradient id="fade" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0.4" stop-color="#fff" />
    <stop offset="1" stop-color="#000" />
  </linearGradient>
  <mask id="soft-bottom">
    <rect width="100%" height="100%" fill="url(#fade)" />
  </mask>
</defs>

<image href="photo.jpg" width="100%" height="100%" mask="url(#soft-bottom)" />
A foto está totalmente visível no topo e esbate-se ao longo dos 60% inferiores.

Em elementos HTML, o CSS mask-image: linear-gradient(#000 40%, transparent) faz o mesmo trabalho, usando o alfa em vez da luminosidade. A técnica da máscara também está por trás dos contornos com gradiente em CSS transparentes.

Evita

  • Reutilizar o mesmo id de gradiente em dois SVG inline na mesma página
  • Esconder um sprite de definições de gradientes com display: none
  • Unidades por omissão em linhas retas
  • Gradientes muito longos, suaves e escuros sem textura

Faz

  • Ids únicos, ou um só sprite de definições partilhado
  • Esconde os sprites com largura e altura zero
  • userSpaceOnUse para contornos e gradientes partilhados
  • Junta grão aos esbatidos grandes, vê textura de ruído em CSS

Perguntas frequentes

Como junto um gradiente a um SVG?

Define um <linearGradient> ou <radialGradient> com filhos <stop> e um id dentro de <defs>, e depois define o fill ou o stroke de uma forma como url(#id).

Porque é que o contorno com gradiente SVG não aparece numa linha?

Uma linha reta horizontal ou vertical tem uma caixa delimitadora de tamanho zero, por isso as unidades objectBoundingBox por omissão falham. Usa gradientUnits="userSpaceOnUse" com coordenadas reais.

Como rodo um gradiente SVG?

Altera x1, y1, x2 e y2, ou junta gradientTransform="rotate(45 0.5 0.5)" para rodar em torno do centro da caixa delimitadora.

Posso mudar as cores de um gradiente SVG com CSS?

Sim. stop-color e stop-opacity são propriedades CSS, por isso regras como stop { stop-color: var(--accent); } funcionam em SVG inline.

Porque é que o meu gradiente SVG desapareceu quando escondi o SVG?

As definições dentro de um SVG com display: none podem não ser desenhadas. Esconde antes o sprite com largura e altura zero, ou com posicionamento absoluto.

Partilhar este guia

Escrito pela GradientlyConta Gradiently verificada

A equipa por trás da Gradiently, uma ferramenta de design construída em torno dos Marks: gradientes vivos que fazem tudo o que crias parecer teu.

Ver o nosso perfil