SVG Filter Effects—3 Simple Filter Primitives

For the last few weeks I’ve been talking about filters in SVG. I showed you the basics, talked in more detail about the filter element, and last week I discussed the input and output of filter primitives. What I haven’t yet done is talk about any of the primitives in detail.

It’s time to change that. Today I want to cover two primitives I’ve shown you already, feGaussianBur and feOffset, but in more detail than I’ve offered to this point. I’ll also talk about a primitive we haven’t seen yet, feFlood.

Next week I’ll talk about two more primitives that are also simple to understand and use and allow you to work with external images and SVG fragments. In the weeks that follow I’ll show you how you can blend and merge images and the effects SVG provides for working with color and lighting effects and finally a few more complex filters that don’t fall under a specific category.

The feGaussianBlur Filter Primitive

The feGaussianBlur filter primitive does what you expect. It performs a Gaussian Blur on the input image or graphic. I’m guessing you’ve added blurs to images in your graphics editor of choice and have an idea what this primitive will do.

The feGaussianBlur filter primitive takes one attribute in addition to the common ones like in, result, and id. The additional attribute is stdDeviation and it’s used in formulas behind the scenes to determine how much blur to apply.

1
stdDeviation = <number-optional-number>

While you don’t need to know the formulas, you should know that the larger the value of stdDeviation, the more blur.

In the examples so far in the series, I’ve used a single value, but stdDeviation can optionally take a second value. If you provide two numbers the first is the standard deviation along the x-axis and the second is along the y-axis. Both axes are those defined in the current coordinate system.

Negative values are not allowed and a value of 0 disables the effect. If you provide two values and only one of them is 0, then there will be no blur in that direction. Not setting any value for stdDeviation is the same as if you set the value to 0.

Since I’ve been using this primitive throughout the series and you may be tired of seeing the same example, let me try a variation of that example.

I created three squares using the <rect> element. The first has no filter applied. The second adds the blur filter with contains an feGaussianBlur primitive with a stdDeviation of 3.

The addition from previous examples is the third square which references the blurrier filter. It also contains an feGaussianBlur primitive, but instead of a single stdDeviation of 3, I changed the value in the x-direction only to 20.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<svg width="100%" height="220" style="outline: 1px solid red">
 <defs>
   <filter id="blur">
     <feGaussianBlur stdDeviation="3" /> 
   </filter>

   <filter id="blurrier">
     <feGaussianBlur stdDeviation="20,3" /> 
   </filter>
</defs>

 <rect x="10" y="10" width="100" height="100" fill="#00f" />
 <rect x="125" y="10" width="100" height="100" fill="#00f" filter="url(#blur)" />
 <rect x="245" y="10" width="100" height="100" fill="#00f" filter="url(#blurrier)" />
</svg>

Here’s the result. Notice that the third square has more blur applied in in the x-direction than the y-direction. You might also notice that because of the additional horizontal blue, this last square is looking less like a square and more like a horizontal rectangle.

One more thing I’ll point out is the feGaussianBlur operation has no effect if the input has an infinite extent as some inputs like FillPaint have. As I mentioned last week, browser support for these infinite extent inputs isn’t quite there and you probably don’t want to use them as I’m writing this, but I thought I would mention it just in case you want to.

The feOffset Filter Primitive

The feOffset filter primitive takes an input and then offsets its location by an amount you specify. You set the amount through either or both of its attributes.

  • dx—amount to offset the input graphic along the x-axis
  • dy—amount to offset the input graphic along the y-axis

Not setting either is the same as if it was set to 0.

The values are in the coordinate system set by the primitiveUnites attribute of the filter element, which can either be userSpaceOnUse or objectBoundingBox. Keep that in mind if you set a value and the element moves by an unexpected amount. If it does, you’re probably in the other coordinate system than what you thought.

Here’s a quick example where I set a filter on a <rect> element that offsets the element by 50px in both the x and y direction. Note that I also increased the width and height of the filter effects region to 160% for each. Otherwise the square would be clipped at the edge of the default region.

1
2
3
4
5
6
7
8
9
<svg width="100%" height="220" style="outline: 1px solid red">
 <defs>
   <filter id="offset" width="160%" height="160%">
     <feOffset in="SourceGraphic" dx="50" dy="50" result="offset" />
   </filter>
 </defs>

 <rect x="0" y="0" width="100" height="100" fill="#00f" filter="url(#offset)" />
</svg>

The original unfiltered element is positioned at the coordinates 0,0 which is the upper left corner of the SVG, but you can see the element sits away from this corner, which is the result of the feOffset filter primitive.

The feFlood Filter Primitive

The feFlood filter primitive lets you set or change both the fill color and opacity of the filtered element. The primitive creates a rectangle filled with the color and opacity values set with two properties, flood-color and flood-opacity.

1
2
flood-color = ( currentColor | <color> \[<icccolor>] )
flood-opacity = ( <opacity-value> | inherit )

You can use any color as the value for flood-color (or use the currentColor) and flood-opacity takes a number between 0.0 and 1.0. If you’re unfamiliar with currentColor, it’s the computed value of the color property. I’m not entirely sure why you would use it in a filter, but I imagine there are some use cases.

The rectangle that’s created by feFlood is as large as the filter primitive subregion. I talked about this subregion a couple weeks ago and you set it through the x, y, width, and height attributes on the filter primitive.

In this example I used the same blue square I’ve used as the source element throughout this series, but notice that I defined a filter effects region from 0 to 200% in both the x and y direction. I also set a filter primitive subregion that extends from 0,0 to 150,100. and filled this subregion with the color green and an opacity of 0.5.

1
2
3
4
5
6
7
8
9
<svg width="100%" height="220" style="outline: 1px solid red">
 <defs>
  <filter id="flood" x="0" y="0" width="200%" height="200%">
   <feFlood in="SourceGraphic" flood-color="green" flood-opacity="0.5" result="flood" x="0" y="0" width="150" height="100" />
  </filter>
 </defs>

 <rect x="0" y="0" width="100" height="100" fill="#00f" filter="url(#flood)" />
</svg>

Even though the SourceGraphic is a 10px0 by 100px blue square, the filter fills in a slightly larger rectangle with a different color and opacity.

To reiterate, feFlood filled the primitive subregion which is 150px by 100px. That’s larger than the original element which was 100px by 100px, but smaller than the filter effects region which extends 200% (200px in this example) in each direction.

Closing Thoughts

I’m guessing all three filter primitives I presented today were easy to understand. There’s a reason I called this post 3 simple filter effects.

In a couple of weeks I’ll show you how to combine feGaussianBlur and feOffset to create a drop shadow and later in the series I’ll show more filter primitives for working with color.

But first I want to show you two more simple primitives that allow you to work with external images and SVG fragments inside filters. That’s where I’ll pick things up next week.

Download a free sample from my book, Design Fundamentals.

Leave a Reply

Your email address will not be published. Required fields are marked *