# Textura de ruído em CSS: acrescentar grão a gradientes com SVG

[Canonical HTML page](https://gradiently.design/pt-pt/guide/css-noise-texture)

Uma ténue camada de ruído esconde as faixas e faz a cor lisa do ecrã parecer impressão ou película. Eis o filtro SVG por trás disto, afinado e pronto a colar.

## The short version

- Uma textura de ruído em CSS faz-se normalmente com um filtro SVG feTurbulence, embebido como uma pequena imagem data URI e repetido em mosaico sobre um gradiente.
- O baseFrequency do feTurbulence define o tamanho do grão: valores mais altos dão grão mais fino, valores mais baixos dão ruído grosso e nebuloso.
- O ruído funciona melhor sobre o gradiente num pseudoelemento, com um modo de mistura como soft-light ou overlay e pouca opacidade.
- O grão esconde as faixas do gradiente porque quebra as arestas visíveis entre tons vizinhos numa variação fina e aleatória.
- Uma imagem de ruído em mosaico é barata de desenhar, enquanto aplicar um filtro SVG ao vivo a um elemento grande, ou animá-lo, custa muito mais.

Uma **textura de ruído em CSS** é um salpico fino e aleatório sobreposto a uma cor ou gradiente para lhe dar grão. O CSS não tem uma função de ruído, por isso a fonte habitual é o SVG: o filtro `feTurbulence` gera o ruído, embrulhas-o num pequeno SVG, embebes isso como data URI e repetes em mosaico sobre o teu gradiente com pouca força. O resultado parece grão de película ou papel impresso, e corrige discretamente as faixas, os degraus visíveis que aparecem em gradientes grandes e suaves.

Porque é que o grão faz a cor parecer mais cara está explicado nos [gradientes com grão](https://gradiently.design/pt-pt/guide/grainy-gradients). Este guia é a implementação.

## O filtro de ruído SVG

```html
<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240">
  <filter id="n">
    <feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="3" stitchTiles="stitch" />
    <feColorMatrix type="saturate" values="0" />
  </filter>
  <rect width="100%" height="100%" filter="url(#n)" />
</svg>
```

Um mosaico de 240 píxeis de ruído cinzento. Guarda-o como noise.svg ou embebe-o como se mostra abaixo.

| Atributo | Valor aqui | O que controla |
| --- | --- | --- |
| `type` | `fractalNoise` | Grão suave e uniforme. O `turbulence` dá ruído mais riscado e ondulado. |
| `baseFrequency` | `0.8` | O tamanho do grão. Cerca de 0,6 a 0,9 é grão fino; 0,1 a 0,3 é nebuloso. |
| `numOctaves` | `3` | Camadas de detalhe. Além de cerca de 4 a diferença é difícil de ver. |
| `stitchTiles` | `stitch` | Faz as arestas do mosaico coincidirem, para as repetições não terem junções. |
| `feColorMatrix` saturate 0 | `0` | Remove a cor aleatória, deixando grão cinzento. |

As definições que importam. A [referência do feTurbulence da MDN](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feTurbulence) documenta o resto.

## Embeber o ruído como data URI

Um ficheiro à parte funciona, mas embeber poupa um pedido e mantém o efeito num só sítio. Num data URI, os carateres que significam algo nos URL têm de ser codificados: `<` passa a `%3C`, `>` passa a `%3E`, `#` passa a `%23` e `%` passa a `%25`. Usa aspas simples dentro do SVG para não chocarem com as aspas duplas à volta do URL.

```css
:root {
  --noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
```

O mesmo mosaico como propriedade personalizada que podes reutilizar em qualquer lado. Esquecer-se de codificar o `#` como `%23` é a razão habitual de não mostrar nada no Firefox.

## Sobrepor o ruído a um gradiente

Põe o ruído num pseudoelemento por cima do gradiente e controla-o com dois botões: um modo de mistura, que decide como o grão cinzento se mistura com a cor por baixo, e a opacidade, que decide a sua força. O `soft-light` mantém as cores limpas e é o mais suave; o `overlay` acrescenta mais contraste. O `pointer-events: none` impede a camada de bloquear cliques.

```css
.grain {
  position: relative;
  isolation: isolate;
  background: linear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6);
}

.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: var(--noise);
  mix-blend-mode: soft-light;
  opacity: 0.45;
  pointer-events: none;
}
```

Grão entre o gradiente e o conteúdo: o texto dentro de `.grain` fica nítido.

- Violeta do entardecer: o grão suaviza: `linear-gradient(135deg, #1e1b4b, #7c3aed 55%, #f472b6)`
- Brilho ardósia: o grão pára as faixas: `radial-gradient(ellipse at 30% 20%, #334155, #0f172a 70%)`
- Aurora pêssego: o grão lê-se como papel: `linear-gradient(180deg, #fef3c7, #fdba74 60%, #fb7185)`

Três gradientes que mais ganham com o grão. Os esbatidos escuros e de baixo contraste, como o do meio, são onde as faixas aparecem primeiro.

Se preferires um único elemento sem pseudoelemento, lista o ruído primeiro em `background-image` e define `background-blend-mode: soft-light, normal`. Perdes o botão de opacidade separado, por isso incorpora a força no SVG, por exemplo com `opacity='0.5'` no `rect`.

## Quanto grão é suficiente

1. **Começa ténue** Começa com `opacity: 0.3` e `soft-light`. Deves mal reparar nele à distância de um braço.
2. **Verifica a zona mais escura** As faixas vivem em esbatidos escuros e lentos. Sobe a opacidade até os degraus aí se dissolverem e pára.
3. **Ajusta o grão ao tamanho** Os heróis de ecrã inteiro aguentam um grão ligeiramente mais grosso, cerca de 0,6. Os cartões e botões pedem grão fino, cerca de 0,9.
4. **Verifica num telemóvel e num monitor grande** Um grão que parece certo num ecrã pode parecer pó noutro. Procura uma textura que se sinta em vez de se ver.
5. **Verifica o texto por cima** O grão não pode reduzir a legibilidade. Se texto pequeno assenta sobre a textura, baixa a força ou mantém o texto numa zona mais calma.

### Demais

- Grão visível do outro lado da sala
- As cores ficam cinzentas e sujas
- Ruído grosso e nebuloso em componentes pequenos
- As arestas do texto parecem difusas contra o salpico

### Mais ou menos certo

- Grão só notado de perto
- As cores ficam limpas com soft-light
- Grão fino ajustado ao elemento
- Faixas desaparecidas, texto nítido

## Desempenho do ruído em CSS

Um data URI em mosaico é barato: o navegador desenha o pequeno mosaico uma vez e repete-o, e uma camada estática é pintada uma vez. A versão cara é aplicar o filtro ao vivo a um elemento grande com `filter: url(#noise)`, que corre o filtro sobre cada píxel sempre que a área repinta. Se animares o grão, para um aspeto de película a cintilar, desloca a camada em mosaico com `transform` em alguns passos aos saltos em vez de regenerar o ruído, e desliga-a para [movimento reduzido](https://gradiently.design/pt-pt/guide/reduced-motion).

```css
.grain {
  overflow: hidden;
}

.grain::after {
  inset: -50%;
  animation: flicker 0.6s steps(3) infinite;
}

@keyframes flicker {
  0%   { transform: translate(0, 0); }
  33%  { transform: translate(-3%, 2%); }
  66%  { transform: translate(2%, -3%); }
}

@media (prefers-reduced-motion: reduce) {
  .grain::after { animation: none; }
}
```

Grão animado ao mover um mosaico sobredimensionado. O inset negativo mantém as arestas cobertas enquanto se desloca.

Um mosaico de ruído PNG ou WebP pré-desenhado de cerca de 128 a 256 píxeis é uma fonte igualmente boa se já tiveres um. O grão é também um ingrediente de uma família mais ampla de superfícies, do papel ao vidro, tratada na [textura de fundo](https://gradiently.design/pt-pt/guide/background-texture). É também a camada final de um [gradiente de malha em CSS](https://gradiently.design/pt-pt/guide/css-mesh-gradient).

O grão está incorporado em todos os Marks da Gradiently como uma definição de material, junto com a luz e o movimento, por isso os designs feitos com um levam textura sem código nenhum.

Um Mark com grão como parte do seu material, desenhado ao vivo em vez de sobreposto depois.

## FAQ

### Como acrescento uma textura de ruído em CSS?

Embebe um SVG com um filtro `feTurbulence` como data URI, repete-o em mosaico num pseudoelemento sobre o teu gradiente e define um modo de mistura como `soft-light` com pouca opacidade.

### Porque não aparece o meu data URI de ruído SVG?

Normalmente por um caráter sem codificar. No data URI, codifica `#` como `%23`, `%` como `%25` e os parênteses angulares como `%3C` e `%3E`, e usa aspas simples dentro do SVG.

### O grão corrige as faixas nos gradientes?

Sim, na maioria dos casos. A variação fina e aleatória quebra as arestas duras entre tons vizinhos, por isso o olho deixa de ver degraus.

### Que baseFrequency devo usar para o grão?

Cerca de 0,6 a 0,9 dá grão fino, tipo película. Valores mais baixos, como 0,2, dão ruído grande e nebuloso.

### O ruído em CSS é mau para o desempenho?

Uma pequena imagem de ruído em mosaico é barata. Os filtros SVG ao vivo em elementos grandes e o ruído regenerado constantemente é que custam mais.
