Chapter 18: SVG Filters Introduction
SVG Filters Introduction!
Up until now, we’ve learned how to draw shapes (<rect>, <circle>, <path>…), color them (fill, stroke), add text, markers, links, images, and more. All of that is already super powerful.
But SVG filters take things to another level. They let you apply Photoshop-like effects (and way beyond) directly inside your SVG — things like blur, drop shadows, glows, color shifts, emboss, turbulence, lighting, distortions, and even completely custom visual effects.
And the best part?
- These effects are vector-based (sharp at any zoom)
- They work on SVG shapes, text, images inside SVG, and even HTML elements (via CSS filter: url(#myFilter))
- They’re non-destructive — you don’t change the original graphic
- You can animate them, combine them, and chain them like layers in editing software
I’m going to explain it like we’re sitting together building effects step by step — slowly, clearly, with examples you can copy-paste right now.
What are SVG Filters really?
An SVG filter is like a processing machine:
- You feed it a graphic (the “source”)
- The machine applies one or more operations (called filter primitives)
- It outputs a modified version of that graphic
All this happens inside a special <filter> element, which lives in <defs> (definitions — like gradients or patterns).
Key idea: <filter> itself is invisible — it’s just a recipe. You attach the recipe to any element using the filter attribute: filter=”url(#myCoolFilter)”
Basic structure (must-know pattern)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<svg width="400" height="300"> <!-- 1. Define the filter in <defs> --> <defs> <filter id="myBlur"> <!-- Primitives go here --> <feGaussianBlur stdDeviation="5" /> </filter> </defs> <!-- 2. Apply it to any shape/text/image --> <circle cx="200" cy="150" r="80" fill="#2196F3" filter="url(#myBlur)" /> </svg> |
Result: Nice soft blurred blue circle.
Important concepts before examples
- Filter primitives — the building blocks All start with fe (filter effect) Examples we’ll use today:
- <feGaussianBlur> → blur
- <feDropShadow> → modern drop shadow
- <feOffset> → move/shift graphic
- <feColorMatrix> → color changes
- <feMerge> → combine results
- Inputs & Outputs Each primitive takes an input (usually previous result or “SourceGraphic”) Produces a result (named with result=”blur”) Next primitive can use that result as input
- SourceGraphic vs SourceAlpha
- SourceGraphic = full colored shape
- SourceAlpha = only the alpha channel (transparency shape, black & white)
- The filter region By default, filters might clip if effect goes outside bounds. Common fix: <filter x=”-50%” y=”-50%” width=”200%” height=”200%”> (expand region)
Example 1 – Simple Gaussian Blur (most popular starting point)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<svg width="320" height="220"> <defs> <filter id="blurMe"> <feGaussianBlur stdDeviation="6" /> <!-- 6 = blur amount --> </filter> </defs> <rect x="40" y="40" width="240" height="140" fill="#4CAF50" rx="12" filter="url(#blurMe)"/> <text x="160" y="110" font-size="42" text-anchor="middle" fill="white"> Blurry! </text> </svg> |
- stdDeviation = blur radius (higher = more blur)
- Try 2, 8, 15 — see the difference!
Example 2 – Classic Drop Shadow (two ways)
Modern easy way (SVG 2 – best in 2025–2026):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<svg width="300" height="180"> <defs> <filter id="shadowEasy"> <feDropShadow dx="4" dy="6" stdDeviation="4" flood-color="#333" flood-opacity="0.5"/> </filter> </defs> <rect x="60" y="60" width="180" height="80" fill="#FF9800" rx="10" filter="url(#shadowEasy)"/> <text x="150" y="110" font-size="36" text-anchor="middle" fill="white"> Shadow! </text> </svg> |
Classic way (still very common – more control):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<svg width="300" height="180"> <defs> <filter id="shadowClassic"> <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/> <feOffset in="blur" dx="5" dy="5" result="offsetBlur"/> <feMerge> <feMergeNode in="offsetBlur"/> <feMergeNode in="SourceGraphic"/> </feMerge> </filter> </defs> <circle cx="150" cy="90" r="60" fill="#673AB7" filter="url(#shadowClassic)"/> </svg> |
Steps:
- Blur the alpha channel
- Offset the blurred shadow
- Merge shadow + original graphic
Here are visual examples of drop shadow variations (imagine seeing these side by side):
- Soft shadow (stdDeviation=4–8)
- Hard shadow (stdDeviation=0 + offset)
- Colored shadow (flood-color=”cyan”)
Example 3 – Color shift / desaturate with <feColorMatrix>
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<svg width="400" height="200"> <defs> <filter id="grayscale"> <feColorMatrix type="saturate" values="0" /> </filter> <filter id="sepia"> <feColorMatrix type="matrix" values="0.393 0.769 0.189 0 0 0.349 0.686 0.168 0 0 0.272 0.534 0.131 0 0 0 0 0 1 0"/> </filter> </defs> <image href="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=600" x="20" y="20" width="160" height="160" filter="url(#grayscale)"/> <image href="https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=600" x="220" y="20" width="160" height="160" filter="url(#sepia)"/> </svg> |
- type=”saturate” values=”0″ → black & white
- Matrix → sepia tone (classic Instagram look)
Quick Cheat Sheet – Most used filters (2025–2026)
| Effect you want | Main primitive(s) used | Key attributes |
|---|---|---|
| Blur | <feGaussianBlur> | stdDeviation=”5″ |
| Drop shadow | <feDropShadow> or <feGaussianBlur> + <feOffset> + <feMerge> | dx, dy, stdDeviation, flood-color |
| Grayscale | <feColorMatrix type=”saturate” values=”0″> | — |
| Sepia / color tint | <feColorMatrix type=”matrix”> | 5×4 matrix values |
| Glow | <feGaussianBlur> + <feMerge> (multiple times) | higher stdDeviation + bright color |
| Brightness/contrast | <feComponentTransfer> | <feFuncR type=”linear” slope=”1.5″/> |
Common beginner mistakes
- Forget id on <filter> → can’t reference it
- No result when chaining → primitives don’t connect
- Filter clips edges → add x=”-50%” y=”-50%” width=”200%” height=”200%” to <filter>
- Using on <line> without stroke → nothing visible
- Expect CSS filter: blur(5px) to be same as SVG → similar but SVG is more powerful/customizable
Mini practice for you
- Apply a soft drop shadow to a rounded rectangle button
- Make a circle that looks “glowy” (blur + bright color merge)
- Turn an embedded photo grayscale with one filter
Paste your code here if you want feedback — I’ll review it like we’re pair-programming 😄
This is just the introduction — filters are huge! Next we can go deeper into blur types, drop shadows with color, glows, displacement maps, turbulence (water/ripples), lighting effects, etc.
Which effect excites you most? Blur? Glow? Color changes? Shadows? Tell me — we’ll zoom in with more examples until it feels fun and easy! 🚀
