Search code examples
csssvgshadowsvg-filtersbox-shadow

How to have a drop shadow on a transparent rect svg


I want to have a drop shadow on a transparent SVG element.

I have tried using all different kinds of filters but to no avail. css3 filters on the svg element(filter: drop-shadow(0 -6mm 4mm rgb(160, 0, 210));), the new dropshadow filter(<feDropShadow>), the old filters:

<filter xmlns="http://www.w3.org/2000/svg" id="dropshadow" height="130%">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> 
      <feOffset dx="2" dy="2" result="offsetblur"/>
      <feComponentTransfer>
        <feFuncA type="linear" slope="0.2"/>
      </feComponentTransfer>
      <feMerge> 
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/> 
      </feMerge>
    </filter>

This can be achieved using css3 box-shadow Codepen

I expect to have a dropshadow on a transparent element but the actual transparent element clips over the dropshadow(so the element itself is transparent, but has an neon like outer glow)

I want to be able to control:

  • blur
  • spread
  • color

Any help will be appreciated :)


Solution

  • You can't do this if the original is a fully transparent shape - because of reasons - but you can do this starting from an almost completely transparent original shape and end up with a fully transparent shape surrounded by a normal drop shadow.

    Draw your shapes with 1% fill-opacity. When you pull those into a filter, multiply their alpha by 100 using a colormatrix - and use that as the basis for your dropshadow. You won't end up using the original 1% opacity shape in your final version because if you use the "out" operator - this discards the contents of anything that overlaps with the original (processed) shape.

    svg {
      background: #33D; 
    }
    <svg width="500px" height="400px">
    <defs>
      <filter id="trans-shadow">
      <feColorMatrix type="matrix" values="1 0 0 0 0 
                                           0 1 0 0 0 
                                           0 0 1 0 0 
                                           0 0 0 100 0"
                                           result="boostedInput"/>
                                           
      <feGaussianBlur stdDeviation="5"/>
      <feComposite operator="out" in2="boostedInput"/>
      </filter>
    </defs>
    
    
    <circle filter="url(#trans-shadow)" x="100" y="100" r="050" cx="150" cy="150" fill="black" fill-opacity="0.01" />
    
    
    </svg>

    I'm assuming that these shapes are not always drop-shadowed, so you want their non drop-shadowed versions to be as transparent as possible. If these shapes are never displayed without a drop-shadow then you can skip a step and just draw these shapes in black originally and still use the "out" to discard them. Like so:

    svg {
      background: #33D; 
    }
    <svg width="500px" height="400px">
    <defs>
      <filter id="trans-shadow">                                          
      <feGaussianBlur stdDeviation="5"/>
      <feComposite operator="out" in2="SourceGraphic"/>
      </filter>
    </defs>
    
    
    <circle filter="url(#trans-shadow)" x="100" y="100" r="050" cx="150" cy="150" fill="black" />
    
    
    </svg>