SVG lighting filters

SVG 라이팅 필터

Treats an alpha channel as a height map and shines a virtual light on it. feDiffuseLighting gives matte shading, feSpecularLighting gives a glossy highlight — together they emboss a flat shape.

Also known as: feDiffuseLightingfeSpecularLightingEmboss filter
···
html
<svg width="0" height="0"><filter id="emboss" x="-30%" y="-30%" width="160%" height="160%">
  <feGaussianBlur in="SourceAlpha" stdDeviation="3" result="b"/>
  <feSpecularLighting in="b" surfaceScale="6" specularConstant="1.1" specularExponent="16" lighting-color="#ffffff" result="s">
    <fePointLight id="light" x="60" y="40" z="60"/>
  </feSpecularLighting>
  <feComposite in="s" in2="SourceAlpha" operator="in" result="sc"/>
  <feComposite in="SourceGraphic" in2="sc" operator="arithmetic" k1="0" k2="1" k3="1.4" k4="0" result="lit"/>
</filter></svg>
<div class="panel"><h1 class="emb">EMBOSS</h1></div>
<div class="label">feSpecularLighting + fePointLight</div>
css
.panel{position:relative;width:min(80%,320px);height:120px;border-radius:16px;background:#23232e;
  display:grid;place-items:center;overflow:hidden}
.emb{margin:0;color:#4b4b5a;font:800 32px/1 sans-serif;letter-spacing:.04em;filter:url(#emboss)}
.label{position:absolute;left:50%;bottom:8%;transform:translateX(-50%);padding:4px 10px;border-radius:999px;
  background:rgba(0,0,0,.55);color:#fff;font:600 12px/1.4 monospace}
js
const light = document.getElementById('light');
let t = 0;
function loop(){
  t += 0.02;
  light.setAttribute('x', (160 + Math.cos(t) * 140).toFixed(0));
  light.setAttribute('y', (60 + Math.sin(t) * 40).toFixed(0));
  requestAnimationFrame(loop);
}
loop();

First, feGaussianBlur softens the original alpha (the silhouette of some text or shape) into a height map. Feed that into feSpecularLighting/feDiffuseLighting and it's treated as a bump surfaceScale units tall, lit by a fePointLight, feDistantLight, or feSpotLight you place. Finally feComposite blends the lighting result back with the source so the shape reads as "raised and catching light."

feDiffuseLighting gives Lambertian shading (matte, equally bright from any viewing angle); feSpecularLighting gives a highlight that only shows where the light and viewing angles line up. A real emboss usually layers both.

Animate a fePointLight's x/y/z and the light appears to sweep across the surface, which sells the depth far better than a static light. This chain is one of the heaviest SVG filters, though — blur, lighting and composite each run per-pixel, several passes deep — so avoid it on large or frequently-resized areas. Safari's rendering of fePointLight's z (height) in particular can differ subtly from other browsers, so treat it as a progressive enhancement.

When to use

For giving a single logo or wordmark a metallic/embossed texture. Don't apply it to body text or layouts that resize often.