SVG Filters
Last Tended:
Status: decay
A filter is like a machine that takes a graphic input, changes it & returns the result. The browser offers 2 types of filters, CSS & SVG. CSS filters are a subset of SVG filters. SVG filters offer a wider range of capabilities. The effects browser filter can produce can also be achieved in image editing software like Photoshop. However, browser filters have 2 advantages. They can be animated & interacted with.
Apply a Filter
A filter can be applied to a:
- ▪ HTML element through the CSS
filter
property. - ▪ SVG element through the
filter
attribute or CSS property.
/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta content="width=device-width, initial-scale=1" name="viewport" /> <style> .filtered { filter: url(#myFilter); } </style> </head> <body> <svg> <defs> <filter id="myFilter"> ... </filter> </defs> </svg> <rect filter="url(#myFilter)" ... /> <img class=”filtered” ... /> </body> </html>
Primitive
An SVG filter is made up of 1 or more filter primitives. All primitives share the same prefix: fe (short for filter effect). A primitive:
- ▪ takes 1 or 2 inputs,
- ▪ performs a fundamental graphical operation &
- ▪ outputs a result.
localhost:3000
<svg> <defs> <filter id="myFilter"> <feGaussianBlur in="SourceGraphic" stdDeviation="3" /> </filter> </defs> </svg> <p>Original:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" /> <p>Filtered:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" class="filter" />
The in
attribute can be:
- ▪
SourceGraphic
: an element (example: image or text). - ▪
SourceAlpha
: the same as sourceGraphic, except only the alpha channel will be read. This is like passing a silhouette of the image to the filter. - ▪ Result from another primitive.
Multiple Primitives
A SVG filter can be made up of multiple primtiives. You can use the result of 1 primitive as the input of the next.
The following example is using the feGaussianBlur
primitive to blur an image, then passing the result to the feOffset
primitive, which moves it 20px
to the right.
localhost:3000
<svg> <defs> <filter id="myFilter"> <feGaussianBlur in="SourceGraphic" stdDeviation="3" result="BLUR_RESULT" /> <feOffset in="BLUR_RESULT" dx="20" /> </filter> </defs> </svg> <p>Original:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" /> <p>Filtered:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" class="filter" />
If in
& result
aren't specified, the result
of the previous primitive is automatically used as the in
of the following primitive.
2 inputs
Each filter primitive can take 1 or 2 inputs (but only ever output 1 result).
The attribute for the 2nd input is in2
.
This example is using the feImage
primitive to output an image.
This & a 2nd image is used as the inputs for feComposite
, which is outputing only where the images overlap.
localhost:3000
<svg> <defs> <filter id="myFilter"> <feImage href="https://garden.bradwoods.io/images/gwenStacy.png" width="240px" x="54px" result="ORIGINAL_2_RESULT" /> <feComposite in="SourceGraphic" in2="ORIGINAL_2_RESULT" operator="in" /> </filter> </defs> </svg> <p>Original 1:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" /> <p>Original 2:</p> <img alt="A superhero." src="https://garden.bradwoods.io/images/gwenStacy.png" /> <p>Filtered:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" class="filter" />
Filter Region
The area where a filter will render to is known as the filter region. The default position & size of this region is:
/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link href="index.css" rel="stylesheet"> </head> <body> <svg> <defs> <filter id="myFilter" width=”110%” height=”110%” x=”-10%” y=”-10%” > ... </filter> </defs> </svg> </body> </html>
The filter region can be visualized using the feFlood
primitive.
It fills the region with a specified color.
localhost:3000
<svg> <defs> <filter id="myFilter"> <feFlood in="SourceGraphic" flood-color="hsl(0, 0%, 0%)" flood-opacity="1" /> </filter> </defs> </svg> <p>Original:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" /> <p>Filtered:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" class="filter" />
If the effect of your filter extends passed this region, it will result in a cut-off effect. This can be avoided by increasing the size of the region.
localhost:3000
<svg> <defs> <filter id="myFilter"> <feGaussianBlur in="SourceGraphic" stdDeviation="12" /> </filter> <filter id="myFilterEnlarged" width="300%" height="300%" x="-100%" y="-100%"> <feGaussianBlur in="SourceGraphic" stdDeviation="12" /> </filter> </defs> </svg> <p>Original:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" /> <p>Filtered:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" class="filter" /> <p>Filtered with enlarged region:</p> <img alt="Graffiti." src="https://garden.bradwoods.io/images/graffiti.png" class="filterEnlarged" />
List of Primitives
Primitive | Description | Resources |
---|---|---|
feBlend | Blends two layers. | |
feColorMatrix | Changes input colors. Used for controlling hue, saturation & brightness. | |
feComponentTransfer | Performs remapping of color for each pixel. Used for adjusting brightness, contrast, color balance & threshold. Used with feFuncA , feFuncR , feFuncG , feFuncB . feFuncA, feFuncR, feFuncG, feFuncB: defines the transfer function for the alpha, red, green & blue component of the input graphic. Input graphic is defined in feComponentTransfer . | |
feComposite | Combines 2 inputs.
| |
feConvolveMatrix | Combines pixels in the input image with neighboring pixels. Used for blurring, sharpening, embossing and beveling. | |
feDisplacementMap | Used to contour an image to a texture. | |
feflood | Fills the filter region with a color. | |
feGaussianBlur | Blurs the input image. | |
feImage | The filter version of the image element (& has the same attributes). It fetches image data from an external source and provides the pixel data as output (if the external source is an SVG, it is rasterized). | |
feMerge | Applies filter effects concurrently instead of sequentially. Used with feMergeNode | |
feMergeNode | Takes the result of another filter. | |
feMorphology | Erodes or dilates the input image. Used for fattening or thinning. | |
feOffset | Translates the image. Used for creating shadows. | |
feTile | Fill a target rectangle with a repeated, tiled pattern of the input image. | |
feTurbulence | Creates an image using the Perlin turbulence function. Used for make textures. | |
feDiffuseLighting | Lights an image using the alpha channel as a bump map. Used with
| |
feSpecularlighting | Lights an image using the alpha channel as a bump map. The resulting image is an RGBA image based on the light color. The lighting calculation follows the standard specular component of the Phong lighting model. The resulting image depends on the light color, light position and surface geometry of the input bump map. The result of the lighting calculation is added. The filter primitive assumes that the viewer is at infinity in the z direction.Produces an image which contains the specular reflection part of the lighting calculation. Used with a texture using the add term of the arithmetic feComposite method. Used with fePointlight & feSpotlight .fePointlight defines a light source which allows to create a point light effect. feSpotlight defines a light source. |
Examples
Scan Lines
Primitives used:
- ▪ feImage
- ▪ feComposite
localhost:3000
<svg class="defs"> <defs> <!-- A pattern of horizontal lines going down the page. --> <pattern id="myPattern" patternUnits="userSpaceOnUse" width="10" height="2" > <line x1="0" y="0" x2="10" y2="0" stroke="black" stroke-width="1" /> </pattern> <!-- A rectangle containing the above pattern. --> <rect id="myRect" x="0" y="0" width="100%" height="100%" fill="url(#myPattern)" /> <!-- Layer the patterned rectangle on top on the source image & remove where the image & lines overlap --> <filter id="myFilter"> <feImage href="#myRect" result="RECT_RESULT"/> <feComposite in="SourceGraphic" in2="RECT_RESULT" operator="out" /> </filter> </defs> </svg> <p>Original img:</p> <img alt="A superhero." src="https://garden.bradwoods.io/images/gwenStacy.png" /> <p>Rectangle with pattern:</p> <svg> <use href="#myRect" /> </svg> <p>Filtered:</p> <img alt="A superhero." src="https://garden.bradwoods.io/images/gwenStacy.png" class="filter" />
Hologram
For a more sophisticated hologram effect, see here. Primitives used:
- ▪ feComponentTransfer
- ▫ feFuncR
- ▫ feFuncG
- ▫ feFuncB
- ▪ feGaussianBlur
- ▪ feComponentTransfer
- ▪ feOffset
- ▪ feMerge
- ▫ feMergeNode
localhost:3000
<svg class="defs"> <defs> <filter id="myFilter"> <!-- Make the source image blue. --> <feComponentTransfer in="SourceGraphic" result="BLUE_RESULT"> <feFuncR type="linear" slope="0"></feFuncR> <feFuncG type="linear" slope="2"></feFuncG> <feFuncB type="linear" slope="20"></feFuncB> </feComponentTransfer> <!-- Blur the blue result (blur in x-direction only). --> <feGaussianBlur stdDeviation="4, 0" edgeMode="none" in="BLUE_RESULT" result="BLUR_RESULT" /> <!-- Reduce the opacity of the blur result. --> <!-- slope = any number, C' = slope * C + intercept --> <feComponentTransfer in="BLUR_RESULT" result="OPACITY_RESULT"> <feFuncA type="linear" slope="0.3" /> </feComponentTransfer> <!-- Translate the reduced opacity result to the left. --> <feOffset dx="-8" dy="0" in="OPACITY_RESULT" result="OFFSET_LEFT_RESULT" /> <!-- Translate the reduced opacity result to the right. --> <feOffset dx="8" dy="0" in="OPACITY_RESULT" result="OFFSET_RIGHT_RESULT" /> <!-- Combine the blue result & 2 translated results. --> <feMerge> <feMergeNode in="OFFSET_LEFT_RESULT" /> <feMergeNode in="OFFSET_RIGHT_RESULT" /> <feMergeNode in="BLUE_RESULT" /> </feMerge> </filter> </defs> </svg> <p>Original:</p> <img alt="A superhero." src="https://garden.bradwoods.io/images/gwenStacy.png" /> <p>Filtered:</p> <img alt="A hologram of someone wearing a spider costume." src="https://garden.bradwoods.io/images/gwenStacy.png" class="filter" />
Distress
Primitives used:
- ▪ feTurbulence
- ▪ feComponentTransfer
- ▫ feFuncA
- ▪ feComposite
localhost:3000
<svg> <defs> <filter id="myFilter"> <feTurbulence type="fractalNoise" baseFrequency="0.1" numOctaves="2" /> <feComponentTransfer> <feFuncA type="linear" slope="89" intercept="-28" /> </feComponentTransfer> <feComposite in="SourceGraphic" operator="in" /> </filter> </defs> </svg> <p>Original:</p> <img alt="A superhero." src="https://garden.bradwoods.io/images/gwenStacy.png" /> <p>Filtered:</p> <img alt="A superhero." src="https://garden.bradwoods.io/images/gwenStacy.png" class="filter" />

Resources
Examples | |
---|---|
Michael Mullany | Codepen profile |
PetitePatterns | Codepen profile |
Yoksel | Codepen profile |
Tools | |
fffuel | Generator |
Gradient Map Filter Generator | Create Gradient Map Filters from given colors |
Method Draw | SVG drawing app (to go menu: View > Source to view source code) |
SVG Filters | Playground, presets & docs |