Left Arrow

Notes

Filters

3 squares of different textures stacked 1 after the other.

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.

3 squares of different textures stacked 1 after the other.

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>
3 squares of different textures stacked 1 after the other.

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.
3 squares of different textures stacked 1 after the other.

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.

3 squares of different textures stacked 1 after the other.

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" />

3 squares of different textures stacked 1 after the other.

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" />

3 squares of different textures stacked 1 after the other.

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.


  • Filtered (over): 'in' is placed in front of 'in2'.
  • Filtered (in): the overlap of 'in' & 'in2' render the 'in' graphic.
  • Filtered (atop): the overlap of 'in' & 'in2' render the 'in' graphic. The area of in2 that doesn't overlap is rendered.
  • Filtered (out): The area of in that doesn't overlap in2 is rendered.
  • Filtered (xor): The areas of in & in2 that don't overlap is rendered.
  • Filtered (lighter): The sum of in & in2 is rendered.
  • Filtered (arithmetic): used for combining the output from the feDiffuseLighting & feSpecularLighting filters with texture data. Each pixel is computed using: result = k1i1i2 + k2i1 + k3i2 + k4. i1 and i2 indicate the corresponding pixel channel values of the input image, which map to in and in2 respectively. k1, k2, k3, and k4 indicate the values of the attributes with the same name.
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 fePointlight & feSpotlight.


  • fePointlight: defines a light source which allows to create a point light effect.
  • feSpotlight: defines a light source.
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" />

A space ship's docking bay with various equipment.

Resources

Examples
Michael MullanyCodepen profile
PetitePatternsCodepen profile
YokselCodepen profile
Tools
fffuelGenerator
Gradient Map Filter GeneratorCreate Gradient Map Filters from given colors
Method DrawSVG drawing app (to go menu: View > Source to view source code)
SVG FiltersPlayground, presets & docs

Where to Next?

└── SVG
Arrow pointing down
YOU ARE HERE
└── Filters
└── feDisplacementMap
A sci-fi robot taxi driver with no lower body