A client asked me to add a glassmorphism effect to their hero section — blur, transparency, a subtle inner glow. The developer suggested a PNG overlay. I pushed back: an SVG filter does the same thing in 12 lines of code, loads instantly, and scales to any screen. Here's what I actually use, filtered down to the effects that work reliably across browsers.
CSS box-shadow works on the bounding box. SVG feDropShadow works on the actual shape. For an irregular icon or a curved path, the difference is night and day:
<filter id="soft-shadow"> <feDropShadow dx="2" dy="4" stdDeviation="3" flood-color="#000" flood-opacity="0.15"/> </filter>
I use dx="2" dy="4" as my default shadow angle (mimics top-left light source). stdDeviation controls blur — 2-3 for UI elements, 5-8 for hero graphics. The MDN docs on feDropShadow cover the full parameter list, but I've never needed more than these four.
feGaussianBlur is the workhorse. Combined with feComposite, it creates the frosted glass effect that's everywhere in 2026 UI:
<filter id="glass"> <feGaussianBlur in="BackgroundImage" stdDeviation="8"/> <feComposite in="SourceGraphic" operator="over"/> </filter>
The catch: BackgroundImage only works when the SVG is inline in HTML, not when loaded as an <img> or background-image. I learned this the hard way after 20 minutes of wondering why my blur wasn't showing. If you need glassmorphism in an <img>-loaded SVG, convert the background to a raster layer first using SVG2PNG.
feColorMatrix lets you shift colors directly in the SVG — no Figma re-export needed. I use it for hover states and dark mode variants of icons:
<filter id="grayscale">
<feColorMatrix type="saturate" values="0"/>
</filter>
<filter id="tint-blue">
<feColorMatrix type="matrix" values="
0.3 0 0 0 0
0 0.3 0 0 0
0 0 1 0 0
0 0 0 1 0"/>
</filter>
The matrix values look intimidating, but I don't calculate them by hand. I use fecolormatrix.com — drag a slider, copy the values. The saturate filter at values="0" gives you a pure grayscale that works in every browser back to IE11, unlike CSS filter: grayscale() which has spotty SVG support.
This is the filter I reach for when a design feels too "clean" — it generates Perlin noise that can simulate paper grain, film grain, or watercolor texture:
<filter id="grain"> <feTurbulence type="fractalNoise" baseFrequency="0.65" numOctaves="3" result="noise"/> <feColorMatrix type="saturate" values="0" in="noise" result="gray"/> <feBlend in="SourceGraphic" in2="gray" mode="multiply"/> </filter>
Apply to a background rect and you get an organic texture that's 300 bytes instead of a 200KB JPEG texture image. I've used this on SaaS landing pages, editorial illustrations, and once on a wine label design (the client thought I'd used a scanned paper texture — I didn't correct them).
feDisplacementMap and feConvolveMatrix are powerful but render inconsistently across browsers. feComponentTransfer doesn't work in Safari without a workaround. And anything with more than 4 filter primitives chained together will tank performance on mobile — I've seen a single over-complicated filter drop a page from 60fps to 12fps on an iPhone SE.
I stick to the four filters above. They cover 95% of design needs, they're fast, and they work everywhere.