# Mesh gradients in SVG: what works today

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

You can write a meshgradient element, and Inkscape will even make one for you, but browsers will draw nothing. These are the techniques that give the same soft, many colour look and actually render.

## The short version

- The meshgradient element was proposed in drafts of SVG 2, but no major browser implemented it, and it is not part of the published standard browsers follow.
- Inkscape can author mesh gradients, and its exports rely on a JavaScript polyfill to render in browsers.
- The most reliable way to get a mesh look in SVG is a few coloured shapes softened with feGaussianBlur, or several radial gradients stacked with transparent edges.
- A raster image exported from a design tool is the simplest option when the gradient never needs to change, and WebP or PNG keep it small.
- Whichever method you choose, add light grain over the result to hide banding in the soft transitions.

A true **SVG mesh gradient** does not work in browsers today. The `<meshgradient>` element appeared in drafts of SVG 2, where colours sit on the corners of a grid of patches and blend across each one, but Chrome, Safari and Firefox never shipped it. To get the soft, many colour look that people mean by a [mesh gradient](https://gradiently.design/guide/mesh-gradients), you build it from things that do render: blurred shapes, stacked radial gradients, a raster image, or a shader.

## What happened to meshgradient

The mesh element was part of the SVG 2 working drafts for several years. It described a surface as rows of Coons patches, each patch with four corner colours and curved edges, which is how gradient meshes work in illustration software. Browser makers did not implement it, and the feature was left out of the version of SVG 2 that moved forward. If you paste mesh markup into a page, the browser ignores it and fills the shape with nothing, or with a fallback colour if you set one.

### Does not render in browsers

- `<meshgradient>` with `<meshrow>` and `<meshpatch>`
- Illustrator gradient meshes saved as live SVG
- Inkscape mesh exported without its polyfill
- `<hatch>` patterns, from the same draft

### Renders everywhere

- Shapes blurred with `feGaussianBlur`
- Several `<radialGradient>` fills, stacked
- An embedded PNG or WebP image
- CSS radial stacks or a WebGL canvas

Inkscape is the notable exception on the authoring side. Its mesh tool produces real mesh markup, and when you save for the web it can include a small JavaScript polyfill that draws the mesh at load time. That works, but you are shipping script to paint a background, and it will not render in places that do not run scripts, such as an `<img>` tag or many email clients.

## Method 1: blurred shapes

This is the closest thing to a mesh in pure SVG. Place three to five filled circles or ellipses where you want each colour, then blur the group heavily. The blur blends neighbouring colours into each other exactly the way a mesh does, and you can move each blob independently.

```html
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice">
  <defs>
    <filter id="soften" x="-50%" y="-50%" width="200%" height="200%">
      <feGaussianBlur stdDeviation="120" />
    </filter>
  </defs>
  <rect width="1200" height="800" fill="#0f0b1e" />
  <g filter="url(#soften)">
    <circle cx="260" cy="200" r="260" fill="#7c3aed" />
    <circle cx="900" cy="160" r="240" fill="#f472b6" />
    <ellipse cx="760" cy="640" rx="360" ry="220" fill="#0ea5e9" />
    <circle cx="200" cy="700" r="200" fill="#312e81" />
  </g>
</svg>
```

Enlarge the filter region so the blur is not cropped at the shape edges. stdDeviation around a tenth of the canvas width gives a mesh feel.

- Violet, pink and sky on ink: `radial-gradient(circle at 22% 25%, #7c3aed 0%, transparent 45%), radial-gradient(circle at 75% 20%, #f472b6 0%, transparent 40%), radial-gradient(ellipse at 63% 80%, #0ea5e9 0%, transparent 50%), linear-gradient(#0f0b1e, #0f0b1e)`
- Ember, rose and butter on cream: `radial-gradient(circle at 20% 30%, #fb923c 0%, transparent 45%), radial-gradient(circle at 80% 25%, #f43f5e 0%, transparent 40%), radial-gradient(ellipse at 50% 85%, #fde68a 0%, transparent 55%), linear-gradient(#fff7ed, #fff7ed)`
- Emerald, teal and indigo: `radial-gradient(circle at 25% 75%, #10b981 0%, transparent 45%), radial-gradient(circle at 70% 30%, #0891b2 0%, transparent 45%), radial-gradient(circle at 85% 85%, #6366f1 0%, transparent 40%), linear-gradient(#071a1a, #071a1a)`

Previews of three blurred blob layouts. The first is the SVG above; the colours sit where the blobs sit.

Blur is not free. A large `feGaussianBlur` is recomputed whenever the SVG repaints, so use this for static backgrounds rather than anything that scrolls or animates. For the same idea done entirely in CSS, see [blurry gradients](https://gradiently.design/guide/blurry-gradient).

## Method 2: stacked radial gradients

Each `<radialGradient>` can fade from a colour to transparent. Fill several full size rectangles, one per gradient, and they overlap into a mesh. No filter is involved, so it is lighter to render than blur and stays sharp at any zoom.

```html
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
  <defs>
    <radialGradient id="a" cx="0.2" cy="0.25" r="0.6">
      <stop offset="0" stop-color="#7c3aed" />
      <stop offset="1" stop-color="#7c3aed" stop-opacity="0" />
    </radialGradient>
    <radialGradient id="b" cx="0.8" cy="0.2" r="0.55">
      <stop offset="0" stop-color="#f472b6" />
      <stop offset="1" stop-color="#f472b6" stop-opacity="0" />
    </radialGradient>
    <radialGradient id="c" cx="0.6" cy="0.85" r="0.65">
      <stop offset="0" stop-color="#0ea5e9" />
      <stop offset="1" stop-color="#0ea5e9" stop-opacity="0" />
    </radialGradient>
  </defs>
  <rect width="1200" height="800" fill="#0f0b1e" />
  <rect width="1200" height="800" fill="url(#a)" />
  <rect width="1200" height="800" fill="url(#b)" />
  <rect width="1200" height="800" fill="url(#c)" />
</svg>
```

Fade to the same colour at zero opacity rather than to `transparent`, which keeps the edges clean in every SVG renderer, including older ones.

This translates almost one to one into CSS, which is often the better home for it. [CSS mesh gradients](https://gradiently.design/guide/css-mesh-gradient) shows the same layering with `radial-gradient()` and explains how to control where colours overlap. The SVG version earns its place when the background has to travel as a file, such as a download or an asset in a design system. More on gradient elements in [SVG gradients](https://gradiently.design/guide/svg-gradients).

Stacked radials, CSS version: `radial-gradient(circle at 20% 25%, #7c3aed 0%, transparent 48%), radial-gradient(circle at 80% 20%, #f472b6 0%, transparent 44%), radial-gradient(circle at 60% 85%, #0ea5e9 0%, transparent 52%), linear-gradient(#0f0b1e, #0f0b1e)`

The SVG above written as one CSS background. Copy it if the gradient only lives on a web page.

## Method 3: export a raster

If you designed a true gradient mesh in an illustration tool and it never needs to change, export it as an image. A 1920×1080 mesh compresses well as WebP and stays smooth as PNG; you can embed it with an SVG `<image>` element or use it as a CSS background. You lose resolution independence, but you keep every curve of the original mesh.

> **Add grain before you export** Smooth mesh transitions band easily once compressed. A light noise layer, such as the one in [SVG feTurbulence](https://gradiently.design/guide/svg-noise-filter), hides the steps and keeps file sizes reasonable.

## Choosing the right method

| Method | File | Scales | Best for |
| --- | --- | --- | --- |
| Blurred shapes | Tiny SVG | Yes | Organic, moving blobs, static backgrounds |
| Stacked radials | Tiny SVG or CSS | Yes | Fast, crisp web backgrounds |
| Raster export | Medium image | No | Exact meshes from illustration tools |
| Inkscape plus polyfill | SVG and script | Yes | Inkscape users who need true patches |
| WebGL shader | Script | Yes | Animated, lit, interactive surfaces |

All five give a mesh look. Only the polyfill renders real mesh patches, and only the shader moves cheaply.

1. **Pick three to five colours** Neighbouring hues blend cleanly. Opposites meet in a muddy middle, as [muddy gradients](https://gradiently.design/guide/muddy-gradients) explains.
2. **Place colours, not stops** Decide where each colour lives on the canvas. That is the whole difference between a mesh and a linear gradient.
3. **Leave a calm area** Keep one region close to the ground colour where a headline will sit.
4. **Finish with grain** A little noise makes the surface feel deliberate and hides banding.

When you want a mesh style background without building one by hand, a Gradiently Mark is a recipe of colours, light, material and grain that renders live at any size, keeps its calmest area behind your words, and exports with Pro as PNG, SVG or PDF. For animated meshes on a website, [shader gradients](https://gradiently.design/guide/shader-gradients) are the next step.

## FAQ

### Do browsers support SVG mesh gradients?

No. The meshgradient element was drafted for SVG 2 but no major browser implemented it, so it renders nothing without a JavaScript polyfill.

### How do I make a mesh gradient in SVG that works?

Blur a few coloured circles with feGaussianBlur, or stack several radialGradient fills that fade to transparent. Both render in every browser.

### Can I use Inkscape mesh gradients on a website?

Yes, if you include the JavaScript polyfill Inkscape can add when saving. Without it, browsers ignore the mesh, and it will not work inside an img tag.

### Is a CSS mesh gradient better than SVG?

For a background that only lives on a web page, CSS radial stacks are simpler. SVG is better when the gradient has to exist as a standalone file.

### Why does my blurred SVG gradient have hard edges?

The filter region is cropping the blur. Enlarge it with x="-50%" y="-50%" width="200%" height="200%" on the filter element.
