# SVG feTurbulence: noise, grain and texture filters

[Canonical HTML page](https://gradiently.design/guide/svg-noise-filter)

One filter primitive makes almost every texture on the web: grain over a gradient, paper behind a card, a wobble on an edge. Here is what each attribute does, with recipes that work.

## The short version

- SVG feTurbulence is a filter primitive that generates Perlin noise, which you can use as grain, paper, clouds or a displacement source.
- The baseFrequency attribute sets the size of the noise: high values around 0.6 to 0.9 give fine grain, and low values around 0.01 to 0.05 give large soft clouds.
- type="fractalNoise" makes soft, even noise suited to grain and paper, while type="turbulence" makes sharper, rippled noise suited to marble and water.
- A small noise tile with stitchTiles="stitch", layered over a gradient at low opacity, adds texture and hides banding at very little cost.
- feTurbulence is expensive to compute over large areas, so render it once as a tile rather than animating it full screen.

**SVG feTurbulence** is a filter primitive that fills its region with Perlin noise. On its own the result is a field of coloured static; combined with other primitives it becomes film grain, paper fibre, clouds, marble or a source for warping shapes. You control it with five attributes: `type`, `baseFrequency`, `numOctaves`, `seed` and `stitchTiles`. Most textures on modern websites, including the grain on [grainy gradients](https://gradiently.design/guide/grainy-gradients), start here.

```html
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300">
  <filter id="noise">
    <feTurbulence type="fractalNoise" baseFrequency="0.75" numOctaves="3" stitchTiles="stitch" />
  </filter>
  <rect width="100%" height="100%" filter="url(#noise)" />
</svg>
```

The minimum: a filter that makes noise, applied to a rectangle. The output is multicoloured static until you remove the colour.

## What each feTurbulence attribute does

| Attribute | Values | Effect |
| --- | --- | --- |
| `type` | `turbulence` (default) or `fractalNoise` | Rippled and sharp, or soft and even |
| `baseFrequency` | One number, or two for x and y | Smaller means larger features |
| `numOctaves` | Whole number, default 1 | Layers of finer detail; costs speed |
| `seed` | Any number, default 0 | A different random pattern |
| `stitchTiles` | `noStitch` (default) or `stitch` | Smooths edges so tiles repeat cleanly |

The five attributes. Change one at a time while you tune, because they interact.

`baseFrequency` is the one you will touch most. It is measured in cycles per user unit, so `0.8` packs features close together and `0.02` stretches them into slow clouds. Two values, such as `baseFrequency="0.01 0.3"`, stretch the noise along one axis, which is how brushed metal and wood grain are faked.

| baseFrequency | Looks like | Use |
| --- | --- | --- |
| 0.8 to 0.9 | Fine film grain | Overlay on gradients and photos |
| 0.5 to 0.7 | Visible grain, risograph | Posters, editorial pages |
| 0.15 to 0.3 | Coarse speckle, concrete | Backgrounds, stone |
| 0.02 to 0.05 | Clouds, smoke | Paper fibres, soft lighting |
| 0.005 to 0.01 | Large slow waves | Displacement, marble |

Starting points for a tile around 300 pixels wide. Noise scales with the SVG, so a tile drawn larger looks coarser.

### type="fractalNoise"

- Soft, cloudlike, evenly spread
- Good for grain, paper and fog
- The usual choice for overlays

### type="turbulence"

- Sharper with dark creases
- Good for marble, fire and water
- Looks busy as a full overlay

## Recipe: grain over a gradient

The most useful thing feTurbulence does is add grain. A clean digital gradient bands into visible stripes, especially dark ones; light noise breaks those stripes up and makes the surface feel printed. The steps: make the noise, strip its colour, then lay it over the gradient at low strength.

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

feColorMatrix with saturate 0 turns the noise grey. Setting the filter region to the full rectangle avoids a soft border.

Save that as `grain.svg` or inline it as a data URI, then tile it in a pseudo element above the gradient.

```css
.hero {
  position: relative;
  isolation: isolate;
  background: linear-gradient(160deg, #0f0b1e 0%, #312e81 55%, #6d28d9 100%);
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: url("/grain.svg");
  background-size: 240px;
  opacity: 0.12;
  mix-blend-mode: overlay;
  pointer-events: none;
}
```

Overlay and soft light blend modes keep the gradient's colour and only add texture. Start at 0.08 to 0.15 opacity and judge it at full screen.

The ground under the grain: `linear-gradient(160deg, #0f0b1e 0%, #312e81 55%, #6d28d9 100%)`

Dark violet gradients like this are where banding shows most, which is exactly where grain earns its place. More on the cause in [gradient banding](https://gradiently.design/guide/gradient-banding).

## Recipe: paper texture

Paper is low frequency noise turned into relief by a light source. `feDiffuseLighting` treats the noise as a height map and lights it from one side, which produces the soft hills of a sheet of cotton paper.

```html
<filter id="paper" x="0" y="0" width="100%" height="100%">
  <feTurbulence type="fractalNoise" baseFrequency="0.04" numOctaves="5" result="noise" />
  <feDiffuseLighting in="noise" lighting-color="#f7f1ea" surfaceScale="2" result="lit">
    <feDistantLight azimuth="45" elevation="60" />
  </feDiffuseLighting>
  <feBlend in="SourceGraphic" in2="lit" mode="multiply" />
</filter>
```

Raise surfaceScale for a rougher sheet; lower elevation for a raking light that exaggerates every fibre.

Pair it with warm off white grounds. [Paper texture backgrounds](https://gradiently.design/guide/paper-texture-background) has palettes that suit it.

## Recipe: warped edges with feDisplacementMap

Noise can also move pixels. `feDisplacementMap` reads the noise and shifts each pixel of the source by up to `scale` units, which gives hand drawn lines, melting type and rippled water.

```html
<filter id="wobble">
  <feTurbulence type="turbulence" baseFrequency="0.02" numOctaves="2" seed="3" result="warp" />
  <feDisplacementMap in="SourceGraphic" in2="warp" scale="10" xChannelSelector="R" yChannelSelector="G" />
</filter>

<text x="40" y="120" font-size="96" font-weight="700" filter="url(#wobble)">Wavy</text>
```

A scale of 4 to 12 reads as hand made. Past 30 the source becomes unrecognisable. Change seed to get a different wobble.

> **Text stays text** Filtered SVG text is still real text, so it can be selected and read by screen readers. Keep warps subtle on anything people need to read.

## Performance and browser behaviour

feTurbulence works in every current browser, but it is computed on the CPU in many of them and its cost grows with area and octaves. A 240 pixel tile is calculated once and repeated, which is cheap. A full screen filter on a live element is recalculated whenever the element repaints, which can be slow on phones.

1. **Tile it** Render noise into a small SVG with `stitchTiles="stitch"` and repeat it as a background image.
2. **Keep octaves low** `numOctaves` above 4 rarely adds visible detail at grain sizes and costs every time.
3. **Avoid animating it** Animating `baseFrequency` or `seed` forces a full recalculation every frame. Shift a static tile with a transform instead.
4. **Check both themes** Grain that looks right on dark can look dirty on light. Tune opacity per theme, as in [dark mode gradients](https://gradiently.design/guide/dark-mode-gradients).

For a CSS only take on the same idea, see [CSS noise texture](https://gradiently.design/guide/css-noise-texture). And if you want grain without tuning filters at all, every Gradiently Mark carries its own grain and material as part of its recipe, rendered live at whatever size you design.

A portrait poster with a deep gradient background and a fine grain texture behind a short headline

A Mark with grain built into its surface. The noise is part of the recipe, so it stays the same scale at every size.

## FAQ

### What does feTurbulence do in SVG?

It generates Perlin noise inside an SVG filter. You can show the noise directly as texture or feed it into other primitives such as feColorMatrix, feDiffuseLighting or feDisplacementMap.

### What baseFrequency should I use for grain?

Try 0.7 to 0.9 with type fractalNoise and three octaves for fine film grain. Lower values make larger, softer features.

### What is the difference between fractalNoise and turbulence?

fractalNoise is soft and even, good for grain and paper. turbulence has sharper creases and suits marble, fire or water effects.

### Why does my SVG noise have visible seams when tiled?

Set `stitchTiles="stitch"` on feTurbulence and set the filter region to the full tile with x, y, width and height, so edges match and no soft border appears.

### Is feTurbulence slow?

It can be on large areas or when animated, because it recalculates the noise on every repaint. A small static tile repeated as a background is cheap.
