Resumindo
- Um gradiente WebGL é desenhado por um shader: um pequeno programa que roda no chip gráfico e decide a cor de cada pixel, muitas vezes várias vezes por segundo.
- Como o shader calcula a cor com matemática em vez de ler uma imagem armazenada, ele pode acrescentar movimento, ruído, grão e luz em qualquer tamanho sem que o arquivo cresça.
- Gradientes shader custam mais para rodar do que gradientes CSS, então um bom shader pausa quando está fora da tela, respeita o movimento reduzido e tem uma alternativa simples em CSS.
- Use CSS para misturas paradas e movimentos simples, e recorra a um shader quando a textura, a profundidade ou o movimento forem o centro do design.
Nesta página
Um gradiente WebGL é um gradiente que o seu navegador pinta com um shader: um programa curto que roda no chip gráfico (a GPU) e responde a uma pergunta para cada pixel da tela, “de que cor você é agora?”. Um gradiente CSS é uma receita fixa de cores e posições. Um shader é uma fórmula, então pode curvar, granular, iluminar e mover a cor, e fazer tudo de novo sessenta vezes por segundo, sem baixar nenhuma imagem.
Você não precisa escrever shaders para criar com eles, mas saber o que eles fazem e o que não fazem ajuda a orientar um desenvolvedor, avaliar uma ferramenta e decidir quando um simples gradiente CSS é a melhor escolha.
O que é um shader, em palavras simples
O WebGL é o jeito de o navegador conversar com a GPU, e todo desenho em WebGL usa dois tipos de shader. O vertex shader posiciona as formas; num gradiente de tela cheia, é só um retângulo cobrindo o canvas. O fragment shader faz o trabalho interessante: roda uma vez por pixel, recebe a posição desse pixel e o tempo atual e devolve uma cor.
Como a GPU roda milhares desses programinhas em paralelo, uma fórmula que seria lenta num código comum fica barata o bastante para ser redesenhada a cada quadro. Aqui está um fragment shader completo para um gradiente de três cores cuja fronteira balança suavemente com o tempo, com uma linha de grão por cima.
#version 300 es
precision highp float;
uniform vec2 u_resolution; // canvas size in pixels
uniform float u_time; // seconds since start
out vec4 outColor;
void main() {
vec2 uv = gl_FragCoord.xy / u_resolution; // 0 to 1 across the canvas
vec3 night = vec3(0.07, 0.04, 0.18); // #120a2e
vec3 violet = vec3(0.49, 0.23, 0.93); // #7c3aed
vec3 coral = vec3(0.98, 0.45, 0.45); // #fa7373
// A slow wave bends the blend so the colours drift.
float wave = sin(u_time * 0.3 + uv.x * 3.0) * 0.08;
float t = clamp(uv.y + wave, 0.0, 1.0);
vec3 color = mix(night, violet, smoothstep(0.0, 0.6, t));
color = mix(color, coral, smoothstep(0.55, 1.0, t));
// Fine grain: a different random value per pixel, per frame.
float n = fract(sin(dot(gl_FragCoord.xy + u_time, vec2(12.9898, 78.233))) * 43758.5453);
color += (n - 0.5) * 0.04;
outColor = vec4(color, 1.0);
}smoothstep suaviza cada transição, a onda senoidal move a fronteira e as últimas linhas acrescentam um grão que também esconde as faixas.Como um gradiente shader difere de um gradiente CSS
Um gradiente CSS é declarativo: você lista cores e posições, e o navegador as pinta. É a ferramenta certa na maior parte do tempo. Um shader é procedural: você descreve como a cor deve se comportar, e a matemática a produz. Essa diferença aparece no que cada um consegue fazer e no quanto cada um custa.
| Aspecto | Gradiente CSS | Gradiente shader |
|---|---|---|
| Definido por | Cores, paradas e uma direção | Uma fórmula executada por pixel |
| Movimento | Posição ou tamanho em movimento, ou propriedades personalizadas animadas | Tudo o que você conseguir expressar em matemática, a cada quadro |
| Textura e grão | Precisa de uma camada extra, como ruído em SVG | Embutidos, e podem se mover |
| Custo para rodar | Muito baixo depois de pintado | Mantém a GPU ocupada enquanto anima |
| Funciona sem JavaScript | Sim | Não: um script prepara o canvas |
| Funciona em e-mail | Em parte, dependendo do cliente | Não |
linear-gradient(180deg, #120a2e 0%, #4c1d95 40%, #7c3aed 62%, #fa7373 100%)Por que os gradientes shader parecem vivos
Três técnicas fazem a maior parte do trabalho, e você vai ouvir os desenvolvedores falarem delas. O ruído é uma aleatoriedade suave: em vez de uma mistura reta, a cor segue uma paisagem de colinas suaves, e é por isso que os gradientes shader parecem orgânicos, e não geométricos. O domain warping realimenta o ruído nele mesmo, e a cor se dobra e rodopia como tinta na água. O tempo desliza a paisagem inteira, o que transforma um campo parado numa deriva.
- O grão pode ser gerado por pixel e por quadro, então cintila como filme em vez de ficar parado como uma textura colocada por cima. Veja gradientes com grão.
- A luz pode ser simulada com poucas linhas: um reflexo que acompanha o ruído parece o brilho da seda ou do vidro.
- A resolução sai de graça. A fórmula roda no tamanho que a tela tiver, então um gradiente shader fica nítido num celular e num monitor 4K com o mesmo código.
- As faixas são mais fáceis de vencer, porque o shader pode acrescentar um pouco de dithering antes de a cor ser arredondada para 8 bits. O guia de banding em gradientes explica por que isso importa.
Use CSS quando
- O gradiente é parado, ou se move de um jeito simples
- Ele fica atrás de muito texto numa página longa
- Precisa funcionar sem scripts, ou em e-mail
- Você precisa dele numa linha de código
Use um shader quando
- O movimento ou a textura são o centro do design
- É uma área principal, não todas as seções
- Você quer grão, brilho ou fluxo que o CSS não simula
- Você pode oferecer uma alternativa em CSS e uma pausa
O custo de um fundo WebGL em movimento
Um shader que anima mantém a GPU trabalhando enquanto está na tela. Num computador de mesa, mal se nota. Num celular mais antigo, pode significar mãos quentes, bateria acabando e uma página que rola com menos suavidade. O custo cresce com o número de pixels e a complexidade da fórmula, então um shader em tela cheia numa tela de alta densidade é o caso mais pesado. O guia gradientes deixam um site lento? mostra como medir.
- 1
Mostre primeiro a alternativa em CSS
Pinte o gradiente parado na hora e faça o canvas aparecer com um esmaecimento quando o shader tiver desenhado o primeiro quadro. Ninguém deve ver uma caixa vazia.
- 2
Verifique se o WebGL está disponível
Alguns navegadores, aparelhos e configurações de privacidade o desativam. Se o contexto não puder ser criado, mantenha a alternativa.
- 3
Respeite o movimento reduzido
Se a pessoa pede menos movimento, desenhe um quadro e pare. O guia de movimento reduzido explica a configuração.
- 4
Pause quando não puder ser visto
Pare o loop de animação quando o canvas sair da área visível ou a aba estiver oculta.
- 5
Renderize numa resolução sensata
Gradientes suaves raramente precisam de todos os pixels do aparelho. Desenhar na metade da resolução e deixar o navegador ampliar pode reduzir muito o trabalho, com um desfoque impossível de notar.
const canvas = document.querySelector('#hero-canvas')
const gl = canvas.getContext('webgl2')
const still = matchMedia('(prefers-reduced-motion: reduce)').matches
let visible = true
if (!gl) {
canvas.remove() // the CSS gradient behind it stays
} else {
new IntersectionObserver(([entry]) => {
visible = entry.isIntersecting
}).observe(canvas)
const frame = (ms) => {
if (visible && !document.hidden) draw(gl, ms / 1000) // your draw call
if (!still) requestAnimationFrame(frame)
}
requestAnimationFrame(frame)
}Para referência, a API WebGL na MDN documenta cada chamada usada aqui, e o caniuse acompanha o suporte ao WebGL2 nos navegadores.
Como criar um gradiente shader: o que colocar no briefing
Você pode dirigir um shader sem ler GLSL. Faça o briefing como faria de um material, e não de uma amostra de cor. Informe a cor de fundo e as três a cinco cores que vivem sobre ela, em hex. Descreva a estrutura: poças suaves, faixas longas, seda dobrada. Diga a velocidade em segundos por ciclo em vez de “devagar”, porque devagar significa coisas diferentes para pessoas diferentes. Diga quanto grão e se ele se move. Por fim, diga onde o texto vai ficar, para que a parte mais agitada do campo fique longe dele.
Como o Gradiently desenha os Marks com shaders
Os Marks do Gradiently são gradientes shader. Cada Mark é uma receita de cores, até três materiais sobrepostos, luz, grão e movimento, e o Studio o desenha ao vivo com WebGL2 atrás de tudo o que você cria. Como é calculado, e não armazenado, o mesmo Mark é renderizado com nitidez em qualquer tamanho de plataforma e se move quando você exporta um vídeo em loop. O renderizador também sabe onde estão as suas palavras, então consegue mover a parte mais calma do campo para trás delas. O guia o que é um Mark explica a receita por completo.

GR·2BAQ·CR
Thistle Mosaic
Ver este MarkPerguntas frequentes
O que é um gradiente WebGL?
É um gradiente desenhado por um shader, um pequeno programa que roda no chip gráfico e calcula a cor de cada pixel. Como é uma fórmula, ele pode se mover, ganhar grão e ser renderizado em qualquer tamanho.
Um gradiente shader prejudica o desempenho?
Um shader parado ou pausado custa pouco, mas um que anima mantém a GPU ocupada enquanto está na tela. Pause-o quando estiver fora da área visível, desenhe numa resolução sensata e mantenha uma alternativa em CSS.
Dá para fazer um gradiente shader sem programar?
Sim. Várias ferramentas de design geram fundos shader a partir de controles, e a Forge do Gradiently cria Marks, que são gradientes shader, a partir de uma frase ou controle por controle.
Os gradientes shader respeitam a configuração de movimento reduzido?
Só se forem feitos para isso. Verifique a media query prefers-reduced-motion em JavaScript e desenhe um único quadro parado quando ela estiver ativa.
O que é GLSL?
GLSL é a linguagem de shaders que o WebGL usa. Os fragment shaders escritos nela decidem a cor de cada pixel, e o navegador os compila para o chip gráfico.
Escrito pelo Gradiently
A equipe por trás do Gradiently, uma ferramenta de design criada em torno dos Marks: gradientes vivos que fazem tudo o que você cria ter a sua cara.
Ver nosso perfil


