CommunityImagemgithub.com

Farhad1618/grainy-gradients

Adiciona granulação de filme (ruído) a gradientes e fundos CSS para que pareçam impressos em vez de plásticos, eliminando bandas de cor. Funciona em um único fundo ou em todo um site/app, onde escaneia o código, lista cada fundo e permite que a pessoa escolha. Mede cada fundo, seleciona a mesclagem e a quantidade, mostra um antes/depois na página real e escreve CSS que se adapta à tela do visitante (HDR/OLED, alto contraste, impressão).

O que é grainy-gradients?

O skill `grainy-gradients` adiciona granulação de filme (ruído) a fundos CSS, transformando gradientes digitais suaves (que parecem 'plásticos' ou 'de computador') em texturas que lembram impressão ou filme, além de eliminar bandas de cor visíveis. Ele funciona tanto para um único fundo específico quanto para um site ou aplicação inteira, escaneando o código-fonte para identificar todos os elementos de fundo e permitindo que o usuário escolha em quais aplicar a granulação. A ferramenta mede automaticamente a luminosidade de cada fundo usando o espaço de cor perceptual CIELAB, seleciona o modo de mesclagem ideal (normalmente soft-light) e a quantidade de ruído (alvos de 0,5 / 0,8 / 1,4 L* para Sutil / Médio / Forte), e gera CSS que se adapta a diferentes telas via media queries: telas HDR recebem menos granulação, configurações de alto contraste recebem menos, e impressão desliga a granulação completamente. O skill é compatível com Claude Code, Cursor e outros terminais que suportam Node.js e automação de navegador, utilizando scripts para capturar screenshots, mostrar comparações antes/depois em uma página de revisão local, e gerar o CSS final pronto para aplicação.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Farhad1618/grainy-gradients/tree/HEAD/skills/grainy-gradients

Installed? Explore more Imagem skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

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:

  1. Quais fundos (apenas quando você escaneou um site inteiro).
  2. Se quer ver um antes e depois primeiro, ou apenas aplicar.
  3. 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 ::before e ::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:

  1. Início, seção de tour: gradiente escuro que aparece gradualmente
  2. Início, hero: brilho radial escuro
  3. Sustentabilidade, cabeçalho: gradiente verde-preto
  4. 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çãoO que ele faz
Gradiente ou cor sólida em um elementoUma 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 gradualmenteA 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 baixoSua 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 imagemUm pseudo-elemento livre, ou um elemento filho se ambos estiverem ocupados.
<img>/<video> preenchendo o elemento, ou um fundo em um pseudo-elementoUm elemento filho em z-index: -1 em um host isolado.
Preto ou branco purosOverlay 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 gradienteRecomenda Uniforme, se Uniforme for claramente mais uniforme. Uniforme fica oculto quando seria o mesmo que Médio.
Alto risco de bandasDiz se a granulação escolhida quebra as listras. Forte faz mais.
Camada de ruído antiga no mesmo fundoSubstitui. 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 o linear-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 --phone ou --colours se 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]

Habilidades Relacionadas