SVG Filters Intro
SVG filters add effects to graphics. Learn filter primitives, the filter region, chaining, and the elements defined in the SVG Filter spec.
Currently, CSS provides a way to apply color effects to images (e.g., lightness, saturation, contrast, etc.) using the filter property. However, CSS filters are limited. They give you a fixed set of single-purpose functions (blur(), brightness(), drop-shadow(), etc.) that you apply to a whole element, mostly for color manipulation and blurring. To create more powerful, composite effects, we’ll need other functions. Such functions are available in SVG.
This page introduces what SVG filters do, the <filter> element and its filter region, and how filter primitives are chained together with the in/result mechanic.
What SVG Filters Do (and When to Use Them)
An SVG filter is a small image-processing pipeline. Instead of a single canned effect, you describe a chain of low-level operations — called filter primitives — where the output of one step becomes the input of the next. By chaining primitives, you can build effects that CSS cannot express on its own:
- Drop shadows and glows built by offsetting, blurring, recoloring, and re-compositing the original graphic.
- Textures and noise generated with
<feTurbulence>(Perlin noise) for clouds, paper, marble, etc. - Displacement / warping with
<feDisplacementMap>, which pushes pixels around using another image as a height map. - Lighting effects that treat the alpha channel as a 3D bump map.
When to choose SVG filters over CSS filters: reach for the CSS filter property when you need a quick, single effect (a blur, a brightness tweak, one drop shadow) on any HTML or SVG element. Reach for SVG filters when you need to combine several operations into one composite effect, generate textures, or do displacement — anything that requires feeding one operation's output into another.
The <filter> Element and Its Region
You define a filter once inside <defs> and reference it from a shape with the filter="url(#id)" attribute (or the CSS filter property). The <filter> element itself doesn't draw anything — it is a container for the primitives that do the work.
A filter has a filter region: a bounding box that limits where the filtered result is rendered. Anything painted outside this region is clipped. The region is controlled by these attributes on <filter>:
| Attribute | Purpose |
|---|---|
x, y, width, height | Position and size of the filter region. Default: x="-10%", y="-10%", width="120%", height="120%" — i.e. 10% padding on each side of the source's bounding box. |
filterUnits | Coordinate system for x/y/width/height. Default objectBoundingBox (values are fractions/percentages of the source bounding box); userSpaceOnUse uses absolute user-space coordinates. |
primitiveUnits | Coordinate system for length values inside the primitives (e.g. feOffset's dx/dy). Default userSpaceOnUse. |
This region is the most common gotcha. Effects like blurs and drop shadows spill outside the original shape, and the default 120% region is often too small — the shadow gets clipped at the edges. If your effect looks cut off, enlarge the region, for example x="-50%" y="-50%" width="200%" height="200%".
Filter Primitives
In SVG, each <filter> element includes a set of filter elements as its children. Each filter primitive performs one basic graphical operation on one or more inputs but outputs only one result. The input is specified in an attribute called in. The result of the operation is specified in the result attribute. The result can then be used as input to other operations. However, if the in attribute is omitted, the primitive defaults to SourceGraphic for the first operation, or the result of the previous primitive for chained operations. All primitives have the same prefix: fe (short for “filter effect”). They are named depending on what an element is or does. E.g., the primitive applying a Gaussian Blur effect to the source graphic is called feGaussianBlur.
Special Input Keywords
Besides naming a previous primitive's result, the in attribute can reference these built-in inputs:
| Keyword | Meaning |
|---|---|
SourceGraphic | The original element the filter is applied to, in full color. |
SourceAlpha | The same element, but only its alpha (transparency) channel — useful as the silhouette for shadows. |
BackgroundImage | A snapshot of the canvas underneath the element. |
BackgroundAlpha | The alpha channel of BackgroundImage. |
FillPaint | The element's fill paint, expanded to fill the filter region. |
StrokePaint | The element's stroke paint, expanded to fill the filter region. |
Note:
BackgroundImage,BackgroundAlpha,FillPaint, andStrokePaintare part of the spec but have little to no browser support today; in practice you'll work withSourceGraphic,SourceAlpha, and theresultof other primitives.
Now there are 17 filter primitives that are defined in the SVG Filter specification.
Filter Elements in SVG
| Element | Description |
|---|---|
<feBlend> | Blends two objects together using generally used imaging software blending modes. |
<feColorMatrix> | Applies a matrix transformation. |
<feComponentTransfer> | Performs component-wise remapping of data. |
<feComposite> | Performs combination of two input images pixel-wise in image space. |
<feConvolveMatrix> | Applies a matrix convolution filter effect. |
<feDiffuseLighting> | Lights an image with the use of the alpha channel as a bump map. |
<feDisplacementMap> | Uses pixel values from the in2 input to displace the in input image. |
<feFlood> | Creates a rectangle which is filled with the opacity and color values from the flood-opacity and flood-color properties. |
<feGaussianBlur> | Applies a Gaussian blur on the input image. |
<feImage> | Refers to a graphic external to this element, that is loaded or rendered into an RGBA raster becoming the result of the primitive. |
<feMerge> | Blends input image layers. |
<feMorphology> | Performs "thinning" or "fattening". |
<feOffset> | Offsets the input image. |
<feSpecularLighting> | Lights a source graphic with the use of the alpha channel as a bump map. |
<feTile> | Fills a target rectangle with a repeated pattern of an input image. |
<feTurbulence> | Creates an image with the Perlin turbulence function. |
<feDropShadow> | Creates a drop shadow effect. |
A Single-Primitive Example
The simplest filter has one primitive. Here feGaussianBlur takes the SourceGraphic and blurs it:
<svg width="200" height="200">
<defs>
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
</defs>
<rect x="10" y="10" width="180" height="180" fill="blue" filter="url(#blur)" />
</svg>Chaining Primitives: a Drop Shadow
The real power comes from chaining. To build a drop shadow by hand, we take the element's silhouette, push it down and to the right, blur it, then place the original graphic back on top. Follow the result/in attributes to see the output of each step flowing into the next:
<svg width="220" height="220">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<!-- 1. Take the alpha (silhouette) of the source -->
<feOffset in="SourceAlpha" dx="6" dy="6" result="offset" />
<!-- 2. Blur that offset silhouette -->
<feGaussianBlur in="offset" stdDeviation="4" result="blur" />
<!-- 3. Stack the blurred shadow under the original graphic -->
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<rect x="20" y="20" width="160" height="160" rx="12"
fill="#1e88e5" filter="url(#shadow)" />
</svg>How the data flows:
feOffsetreadsSourceAlpha(the shape's silhouette) and shifts it bydx/dy, writingresult="offset".feGaussianBlurreadsin="offset"and softens it, writingresult="blur".feMergestacks layers bottom-to-top: first theblur(the shadow), then the unblurredSourceGraphicon top — so the crisp shape sits over its soft shadow.
Note the enlarged filter region (width="140%" height="140%") so the offset, blurred shadow isn't clipped.
For ready-made shortcuts, see the <feDropShadow> primitive and the SVG blur effects chapter. A full attribute listing for every primitive is in the SVG reference.