Gradientes granulados (Grainy gradients)
Gradientes digitais suaves são lidos como "computador". Uma camada de ruído fino faz com que sejam lidos como impressão ou filme, e esconde as bandas (faixas visíveis onde um gradiente passa de um nível de cor de 8 bits para o próximo).
Você faz todo o trabalho. A pessoa apenas olha e escolhe. Nunca pergunte sobre modos de mesclagem, opacidade ou números. A pessoa toma três tipos de decisão, e nada mais:
- Quais fundos (apenas quando você escaneou um site inteiro).
- Se quer ver um antes e depois primeiro, ou apenas aplicar.
- Qual opção parece melhor na pré-visualização.
Como pensar sobre isso
-
Granulação é textura, não cor. Ela não deve clarear, escurecer ou tingir. O ruído está centrado no cinza médio, então a mudança de brilho deve ser próxima de 0. Não pode ser aplicado em preto ou branco puros, e o relatório informa isso.
-
Meça o que é visível, não a opacidade. A granulação visível é a dispersão de L* (luminosidade CIELAB, 0–100), e L* é perceptual, então o mesmo número parece igual em qualquer cor. Abaixo de aproximadamente 0,45 ninguém consegue ver. Os alvos são 0,5 / 0,8 / 1,4 para Sutil / Médio / Forte.
-
Uniforme é importante em gradientes que vão do claro ao escuro. Overlay coloca a maior parte da granulação nas partes mais claras. Uniforme escolhe a mesclagem (geralmente soft-light) que a distribui de forma mais equilibrada. As pessoas tendem a preferir.
-
A granulação pertence ao fundo. Ela fica logo acima do fundo, abaixo de tudo o mais, e acompanha o fundo onde quer que ele vá. Se o fundo aparece gradualmente, a granulação aparece junto.
-
Ela se adapta à tela de cada visitante. Sites não podem distinguir OLED de LCD, mas CSS pode detectar telas HDR (a maioria dos celulares OLED, laptops XDR) e a configuração de alto contraste. O CSS inclui essas media queries:
- fundos escuros recebem um pouco menos de granulação em telas HDR
- a configuração de alto contraste recebe menos granulação
- a impressão desliga a granulação
Tudo é CSS, sem script no site ao vivo.
-
Pule o que a granulação não pode ajudar:
- itens pequenos (botões, badges, ícones)
- texto gradiente
- sobreposições translúcidas e desbotamentos sobre fotos
- padrões de listras e hachuras
1. Qual foi a forma de solicitação?
- Um lugar ("o hero parece sem graça", "adicione granulação ao rodapé"): vá para Encontrar um fundo.
- O site ou app inteiro ("revise meu código", "verifique todos os meus gradientes", "faça o site inteiro"): vá para Escaneie o site inteiro.
2a. Encontrar um fundo
Encontre o elemento que realmente pinta o fundo. Verifique:
- o próprio elemento, e seus
::beforee::after - camadas de tamanho completo dentro dele ou atrás dele (seções frequentemente obtêm sua cor de uma div posicionada absolutamente separada)
Com uma ferramenta de navegador, liste os candidatos:
[...document.querySelectorAll('#section, #section *')].flatMap(e => [null, '::before', '::after'].map(p => [e, p, getComputedStyle(e, p)]))
.filter(([, p, c]) => (!p || c.content !== 'none') && (c.backgroundImage !== 'none' || c.backgroundColor !== 'rgba(0, 0, 0, 0)'))
.map(([e, p, c]) => `${e.tagName.toLowerCase()}${e.id ? '#' + e.id : ''}.${[...e.classList].join('.')}${p || ''} | ${c.position} | opacity ${c.opacity} | ${(c.backgroundImage !== 'none' ? c.backgroundImage : c.backgroundColor).slice(0, 80)}`)
Sem um navegador, leia o CSS. De qualquer forma, procure no CSS por outras versões desse fundo: media queries (layouts de celular frequentemente trocam o gradiente) e regras de modo escuro. Anote-os para o passo 5.
Depois vá para passo 3.
2b. Escaneie o site inteiro
node <pasta deste skill>/scripts/scan.mjs <pasta do projeto>
Ele lê folhas de estilo (regras, media queries, propriedades customizadas), marcação e componentes (classes de gradiente do Tailwind, estilos inline, CSS-in-JS) em cerca de um segundo. Ele classifica o que encontra em quatro grupos:
- Bons candidatos: fundos grandes.
- Vale a pena ver: tamanho desconhecido a partir do código.
- Já tem granulação.
- Pular, com o motivo.
Ele também lista quais páginas carregam cada folha de estilo. Adicione --json para os dados completos.
Classifique você mesmo os que "vale a pena ver". Antes de mostrar a lista, classifique-os com base no que você pode ver. Com uma ferramenta de navegador, meça o tamanho deles na página. Caso contrário, leia a marcação. Mova cada um para bom ou pular. Não envie para a pessoa uma lista de coisas que você poderia ter verificado.
Depois mostre a lista, curta, uma linha cada, em palavras simples, agrupadas por página. Por exemplo:
Encontrei 6 fundos que poderiam receber granulação:
- Início, seção de tour: gradiente escuro que aparece gradualmente
- Início, hero: brilho radial escuro
- Sustentabilidade, cabeçalho: gradiente verde-preto
- Carreiras, faixa "feito aqui": gradiente laranja-preto
Pulando 12: botões, texto gradiente, sobreposições de foto e padrões de listras. A página de citação já tem granulação, mas em uma quantidade que ninguém vê, então eu refaria.
Depois deixe-os escolher. Se você tiver uma ferramenta de pergunta de múltipla escolha (AskUserQuestion no Claude Code), use-a:
- Pergunte "Quais fundos devem receber granulação?" com Todos (Recomendado) primeiro.
- Para até 3 itens adicionais, liste cada um como uma opção com multi-seleção ativada.
- Se houver mais de 4, pergunte primeiro "Todos, ou escolher?"; em "escolher", faça perguntas de múltipla escolha de até 4 itens cada.
Sem a ferramenta, peça para eles responderem com "todos" ou os números.
3. Pergunte: antes/depois, ou apenas aplique?
Pergunte uma vez, para tudo escolhido: "Você quer ver um antes e depois primeiro, ou devo apenas aplicar o melhor para cada um?" Use a ferramenta de múltipla escolha se tiver, com Mostre-me primeiro (Recomendado) e Apenas aplique.
As ferramentas abaixo precisam de Node 22+ e um Chrome, Chromium, Edge ou Brave na máquina (encontrados automaticamente; CHROME_PATH substitui). Elas abrem as páginas headless, então o site deve estar acessível: um servidor de desenvolvimento em execução, uma URL de staging, ou file:// para HTML simples. Nada é adicionado ao site.
4. Mostrar o antes/depois
Mostre-me primeiro: a página de revisão
Execute em segundo plano (ela espera a pessoa) com uma --url por página e os seletores dessa página depois dela:
node <skill>/scripts/review.mjs --url http://localhost:3000/ --selector ".hero" --selector ".footer-band" \
--url http://localhost:3000/about --selector ".about-header"
- Ela tira as fotos sozinha. Para cada fundo, fotografa a página como está e com cada opção, além do que as telas HDR e a configuração de alto contraste obtêm. Isso leva cerca de 10 a 30 segundos por página.
- Depois ela abre uma página de revisão local no navegador da pessoa e imprime o endereço; dê o link também.
- Cada fundo recebe um cartão com:
- um controle deslizante de antes/depois
- Zoom nas bandas, que amplia a área que mais apresenta bandas (granulação fina é invisível em uma imagem reduzida)
- as opções como abas, com a recomendada destacada
- um botão de alternância de Tela
- os números medidos, e um "Porquê" com o relatório
- "Pronto, enviar minhas escolhas" envia as escolhas de volta diretamente. Sem copiar e colar.
Diga a eles em uma linha o que fazer: "Arraste em cada imagem, tente Zoom, escolha um por fundo, depois pressione Pronto." Quando o comando terminar, sua saída tem as escolhas, o CSS para cada fundo, e uma pasta de linha de base por fundo para a verificação no passo 7.
Também mostre uma imagem no chat. Cada pasta de linha de base tem compare-<opção>.png:
- antes/depois completo
- um detalhe ampliado
- o mesmo detalhe com seu contraste esticado, para que as bandas apareçam como listras e a granulação como ruído
- os números medidos
Envie a recomendada para a pessoa (com uma ferramenta de envio de arquivos se tiver; caso contrário, dê o caminho). É a evidência de que a mudança é real.
Apenas aplique
Tire a linha de base e as fotos primeiro, para que o resultado possa ser verificado e mostrado:
node <skill>/scripts/shoot.mjs --url http://localhost:3000/ --selector ".hero" --option recommended --out ./grain-shots
Ele imprime uma linha por imagem (granulação, brilho, largura da banda) e escreve <out>/<seletor>/ com report.json (o relatório, o CSS para cada opção, a recomendada) e compare-<opção>.png. Use o CSS recomendado de report.json.
Sem Chrome, ou o site não pode ser acessado headless
Recorra à pré-visualização na página: copie dist/grain-page.js ao lado dos scripts do próprio site (verifique se carrega, 200 não 404), adicione <script src="/js/grain-page.js" data-grain=".hero | .footer" defer></script>, e peça para eles abrirem a página com ?grain. Ela mostra as mesmas opções com uma alça arrastável na página real; Copiar escolhas copia grain: <opção> + a aparência para cada fundo, que você canaliza para node <skill>/scripts/grain.js --look - para o CSS. Remova a tag e o arquivo depois.
Sem nenhum navegador, escreva a aparência você mesmo e execute grain.js nela:
{ "selector": ".hero", "kind": "gradient", "shape": "linear",
"colours": [{ "colour": "#323435", "pos": 0 }, { "colour": "#141617", "pos": 1 }],
"lengthPx": 900, "background": "linear-gradient(...)", "behind": "#ffffff",
"solidBase": true, "position": "relative", "freePseudo": "::after", "moves": null }
ou node grain.js --colours "#323435,#2a2c2d@24%,#141617" --length 900 --selector ".hero" [--shape radial] [--fade-over "#fff"] [--option even].
O que o motor decide, para que você não precise
| Situação | O que ele faz |
|---|---|
| Gradiente ou cor sólida em um elemento | Uma camada: o ruído se torna a camada de fundo superior do elemento (background-blend-mode), mantida em uma propriedade customizada --grain. Um valor é adicionado a cada lista de fundo, para que os tamanhos, posições e mesclagens da página sejam mantidos. Não pode cobrir texto. |
| Fundo aparece gradualmente | A mesma camada única, então a granulação aparece junto. O relatório dá a granulação em cada estágio do desaparecimento. |
| Gradiente translúcido sem nada sólido por baixo | Sua própria camada (um ::after/::before livre, ou um elemento filho) para que se misture com o que aparece através, em vez de ficar cinza. |
| Fundo de foto ou imagem | Um pseudo-elemento livre, ou um elemento filho se ambos estiverem ocupados. |
<img>/<video> preenchendo o elemento, ou um fundo em um pseudo-elemento | Um elemento filho em z-index: -1 em um host isolado. |
| Preto ou branco puros | Overlay e soft-light não podem adicionar granulação lá, então usa screen ou multiply com uma pequena mudança de brilho, e informa isso. |
| Granulação desigual no gradiente | Recomenda Uniforme, se Uniforme for claramente mais uniforme. Uniforme fica oculto quando seria o mesmo que Médio. |
| Alto risco de bandas | Diz se a granulação escolhida quebra as listras. Forte faz mais. |
| Camada de ruído antiga no mesmo fundo | Substitui. Se o ruído antigo estiver em outro lugar (um pseudo-elemento), diz para removê-lo. |
| Parte do fundo desenhada em uma cena WebGL/canvas (um chão 3D, um fundo de shader) | CSS atrás do canvas não pode alcançá-la, então a parte do canvas parece suave ou manchada ao lado de um céu granuloso. Você adiciona: no shader de fragmento desse material, após a conversão de espaço de cor, soft-light o mesmo tile de ruído no espaço de tela (gl_FragCoord.xy / tilePx, tile = 200 × proporção de pixels do renderizador). Leia o tile e a quantidade da propriedade customizada --grain da página, para que as quantidades de celular, HDR e alto contraste sejam transferidas, e releia no redimensionamento. Meça renderizando um quadro e lendo os pixels. |
| Telas HDR, alto contraste, impressão | @media (dynamic-range: high) e @media (prefers-contrast: more) recalculam a quantidade para essas telas, com a mesma mesclagem. @media print desliga. Uma regra que resultaria igual é omitida. |
As cores são ponderadas por quanto do gradiente cobrem. Um destaque fino não conta tanto quanto a grande área escura, então as versões para celular e desktop da mesma seção recebem o mesmo tratamento.
5. Aplicar
- Coloque cada bloco CSS onde esse fundo está definido, com seu comentário.
- Mantenha a expressão de fundo do próprio projeto. O motor trabalha a partir de valores computados, então coloque de volta
var(--slate)ou olinear-gradient(...)original onde a saída repete um gradiente resolvido longo. - Faça cada versão de cada fundo (celular, modo escuro). O CSS de uma camada vai no mesmo seletor dentro da mesma media query. Meça cada versão com
--phoneou--coloursse diferir. - Método filho: adicione o
<div class="grain-layer" aria-hidden="true"></div>onde o comentário diz (em um componente, em sua marcação). - Use uma propriedade customizada para uma URL de ruído repetida. Se várias regras usam a mesma, defina uma vez.
- Se o relatório listar "Desbotamentos sobrepostos", dê a cada um a mesma granulação conforme descrito lá, ou ele criará bandas novamente onde estiver mais escuro.
- Remova qualquer coisa temporária (uma tag de pré-visualização,
grain-page.js).
6. Verificar, de cada vez
Antes de dizer que está pronto, verifique cada fundo em relação à sua linha de base:
node <skill>/scripts/check.mjs --url http://localhost:3000/ --selector ".hero" --baseline <pasta de linha de base> [--option even]
Ele fotografa a página novamente e imprime PASS/FAIL para cada um destes:
- A camada de granulação está na página (o CSS carregou e está no seletor correto).
- Nenhum novo erro na página.
- A granulação está próxima da quantidade esperada.
- O brilho não mudou.
- As listras ficaram mais estreitas.
- Nada fora do fundo mudou.
- Nenhum elemento se moveu ou mudou de tamanho.
Ele escreve check.png, antes vs agora. Em qualquer FAIL, corrija e execute a verificação novamente; não relate sucesso sobre uma falha. Se um FAIL não puder ser corrigido, diga exatamente qual verificação falhou e por quê.
7. Relatório
Uma ou duas frases por fundo, ou uma lista curta para um site inteiro: o que é, o que foi escolhido e por quê. Adicione o resultado medido da verificação (por exemplo "granulação 0,83 L*, listras 80px → 0,7px, nada mais mudou") e envie check.png ou a imagem compare. Diga uma vez que a granulação se adapta a telas HDR e à configuração de alto contraste e desliga na impressão. Se o relatório disser que um alvo não é confirmado visualmente para aquele tipo de fundo, diga isso brevemente.
Ajustes posteriores
- "Muito" ou "não consigo ver": mova um nível.
-
…
[truncado para tradução]