SVG Evolution 3: Applying Polish
Drop Shadows
We first need to define what we mean by "drop shadow": We would like a fuzzy, darkened region that appears under the thumbnail image in the same rough shape and size of the thumbnail image rectangle, but offset by 5-10 pixels to the right and down.
feGaussianBlur, defs, SourceAlpha
The first thing we will try is to use the feGaussianBlur filter primitive to generate the "fuzzy region":
<svg viewBox="0 0 100 100">
<defs>
<filter id="drop-shadow">
<feGaussianBlur in="SourceGraphic" stdDeviation="4" />
</filter>
</defs>
<circle fill="blue" cx="50" cy="50" r="40" filter="url(#drop-shadow)" />
</svg>
We have named the filter "drop-shadow" here and placed it in the defs section of the SVG document. The defs element is used for creating definitions of elements that will be referenced later in the document. The "drop-shadow" filter has one element, a feGaussianblur filter primitive element. The blue circle specifies to the renderer that it should apply the "drop-shadow" filter before sending the circle's visual output to the screen. We do this by specifying the filter attribute: filter="url(#drop-shadow)".
The feGaussianBlur filter primitive has a couple important settings that we must pay attention to. The in attribute has been set to the special value SourceGraphic. This tells the renderer that the blur filter primitive uses the source image (in this case, the blue circle) as its input. The attribute stdDeviation describes how blurry the output should be. The results of this filter as shown in Figure 2.
The blurry circle looks a little bit like a shadow now, except for the fact that it's the wrong colour. We want our shadow to be black. The easiest way to change this is instead of using SourceGraphic as the input to the feGaussianBlur primitive, we use SourceAlpha (i.e. only the alpha channel of the blue circle) as input to the filter. To do this, we set the in attribute of the feGaussianBlur filter primitive to be SourceAlpha (that is in="SourceAlpha"). The results are shown below:
feBlend, feOffset
There, now that looks like a shadow of a circle! But we have a problem - we're missing the original blue circle now. Thankfully, we can use the feGaussianBlurfeBlend filter primitive to tell the renderer that it should combine/blend the original source image with the output of the feGaussianBlur primitive. That is layer the two on top:
<svg viewBox="0 0 100 100">
<defs>
<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="4" />
<feBlend in="SourceGraphic" in2="blur-out" mode="normal"/>
</filter>
</defs>
<circle fill="blue" cx="50" cy="50" r="40" filter="url(#drop-shadow)" />
</svg>
Here, we've added a new filter primitive to our "drop-shadow" filter. The feBlend primitive combines the original source image with the output of the feGaussianBlur stage. However, there is a problem with this approach: the shadow is in the same location as the blue circle, so it will get almost completely covered by the blue circle that is rendered on top by the feBlend element. We need to add one more filter primitive to our chain, the feOffset filter primitive.
The feOffset filter primitive shifts the image in the x and/or y direction by a given amount. It is useful for specific scenarios like drop shadows. The final filter code looks like:
<svg viewBox="0 0 120 120">
<defs>
<filter id="drop-shadow" filterUnits="userSpaceOnUse" width="120" height="120">
<feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="4" />
<feOffset in="blur-out" result="the-shadow" dx="8" dy="8"/>
<feBlend in="SourceGraphic" in2="the-shadow" mode="normal"/>
</filter>
</defs>
<circle fill="blue" cx="50" cy="50" r="40" filter="url(#drop-shadow)" />
</svg>
Note that the output of the feGaussianBlur now gets sent to the feOffset primitive, where it is shifted over by 8 pixels in the x and y directions. Then, the output of the feOffset primitive is blended with the original graphic by sending both as inputs to the feBlend filter primitive to achieve the final result. The attributes which were added to the filter element were necessary to tell the rendered that the user coordinates should be used and to specify the filter output region. The results of this filter are:
The beauty of this is that any SVG element can use this "drop-shadow" filter element to acquire a drop-shadow just by adding filter="url(#drop-shadow)" as an attribute of that element.
Updating the SVG Image Gallery
You can see the SVG Image Gallery updated with drop shadows on the thumbnail images at the top. Note that I had to slightly shrink the thumbnails further such that the drop shadows and images all fit within the original region of space defined by the object element.
Now let's move on to provide some useful functionality using SVG Filters.



