Filtering in SVG

By mbystedt on Mar 3, 2014, 7:13:48 AM

Filtering can be used to create special effects that really make an image pop. Filters manipulate raster images instead of vector graphics. So, everything in this section talks about pixels and images instead of vectors. SVG viewer support for filters is often weak but the major browsers have been improving.

The filter element is a container for one or more filter effects. The effects are what describe what the filter does. The filter is used by referencing it using the filter attribute that all graphic elements and container elements have. Thus, filters need to have an id attribute. With a basic filter, the other attributes can be left alone.

Adding a filter means that the contained vector graphics are no longer directly rendered. The rasterized image of the vector graphics can be used as input to the filter effects. There is no rule that the contained graphics must be used at all. So, a filter with no effects would just hide what it is attached to.

  <filter id="myPrettyFilter">
    <!-- fe elements go here-->
<rect x="10" y="10" width="200" height="200" filter="url(#myPrettyFilter)" />
Code 1. The basic layout of how filters are defined and used.
The unique id required to reference this filter.
'userSpaceOnUse' or 'objectBoundingBox'. The second value makes units of x, y, width, height a fraction (or percentage) of the object bounding box which uses the filter. (default: objectBoundingBox)
x, y
The clipping plane of the filter.
width, height
The clipping plane of the filter.
'userSpaceOnUse' or 'objectBoundingBox'. Alters the units that filter effects express themselves in. The second value makes units of x, y, width, height a fraction (or percentage) of the filter's bounding box.
Optional: The width and height in pixels of any intermediate images created to display the filter. Values separated by whitespace or a comma. By default, the SVG viewer will pick values appropriate for the device rendering the file.

Filter Bounds

When a graphic element or container element uses a filter, an offscreen raster image is created. The size of this image is controlled by the filter dimension attributes. Each effect renders within the box established by the filter. That means filter effects and the image of the vector graphics the filter is attached to are cropped to that box. Finally, the resulting raster image is layered like any other SVG element.

  <filter id="passThrough" >
    <!-- x: -10%, y: -10%, width: 120%, height: 120% -->
    <feOffset in="SourceGraphic" />
  <filter id="ptOffset" >
    <!-- Move 20% over -->
    <feOffset in="SourceGraphic" dx="20" />
  <filter id="ptOffsetWider" width="140%">
    <feOffset in="SourceGraphic" dx="20" />
<g stroke="skyblue" stroke-width="2" fill="none" >
  <circle cx="70" cy="80" r="50" />
  <circle cx="230" cy="80" r="50" filter="url(#passThrough)" />
  <circle cx="390" cy="80" r="50" filter="url(#ptOffset)" />
  <circle cx="550" cy="80" r="50" filter="url(#ptOffsetWider)" />
Example 1. This shows how filterUnits="objectBoundingBox" by default creates a filter area around what uses it. The circle's bounding box is shown in light grey. The filter's bounding box is shown in red. (Download)
  <filter id="userSpaceDemo" filterUnits="userSpaceOnUse" 
    x="100" y="50" width="200" height="100">
    <feOffset in="SourceGraphic"  />
<g stroke="skyblue" stroke-width="2" fill="green" >
  <circle cx="100" cy="60" r="50" opacity=".1" />
  <circle cx="100" cy="60" r="50" filter="url(#userSpaceDemo)" />
Example 2. This shows how filterUnits="userSpaceOnUse" can define the filter area without using the bounding box of any graphic. The circle's bounding box is shown in light grey. The filter's bounding box is shown in red. (Download)

Putting it Together: Drop Shadow

One common effect that seems to be missing from the list of SVG filter effects is a drop shadow. That is a pretty common (and overused) effect. The secret is that with the other filters and smart use of named results you can build a drop shadow yourself. This example could be extended with a feColorMatrix effect to color the shadow.

  <filter id="dropShadow">
    <!-- Blur the source alpha to make a nice shadow. -->
    <feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur"/>
    <!-- Move the shadow over a bit. -->
    <feOffset in="blur" dx="3" dy="3" result="offsetBlur"/>
    <!-- Put everything together. Blur then graphic. -->
      <feMergeNode in="offsetBlur"/>
      <feMergeNode in="SourceGraphic"/>
<text x="320" y="35" text-anchor="middle" fill="green" stroke="black" 
  font-size="40" filter="url(#dropShadow)">
  Look at my beautiful shadow.</text>
Example 3. A filter that makes a drop shadow. (Download)
Related Topics